<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Vue 路由 | Justic</title><meta name="keywords" content="Vue"><meta name="author" content="Justic"><meta name="copyright" content="Justic"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="Vue Router一、Vue Router 介绍1、路由简介路由是一个比较广义和抽象的概念，路由的本质就是对应关系。 在开发中，路由分为：  后端路由 前端路由  后端路由  概念：根据不同的用户 URL 请求，返回不同的内容 本质：URL 请求地址与服务器资源之间的对应关系   SPA（Single Page Application）  Ajax 前端渲染（前端渲染提高性能，但是不支持浏览器的">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue 路由">
<meta property="og:url" content="http://example.com/2022/07/13/Vue/Vue%20Router/vueRouter/index.html">
<meta property="og:site_name" content="Justic">
<meta property="og:description" content="Vue Router一、Vue Router 介绍1、路由简介路由是一个比较广义和抽象的概念，路由的本质就是对应关系。 在开发中，路由分为：  后端路由 前端路由  后端路由  概念：根据不同的用户 URL 请求，返回不同的内容 本质：URL 请求地址与服务器资源之间的对应关系   SPA（Single Page Application）  Ajax 前端渲染（前端渲染提高性能，但是不支持浏览器的">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg">
<meta property="article:published_time" content="2022-07-13T12:05:37.000Z">
<meta property="article:modified_time" content="2022-07-21T08:33:22.987Z">
<meta property="article:author" content="Justic">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2022/07/13/Vue/Vue%20Router/vueRouter/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Vue 路由',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-07-21 16:33:22'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><!-- hexo injector head_end start --><link rel="stylesheet" href="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.css" /><!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.2.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://portrait.gitee.com/uploads/avatars/user/2982/8948190_JIAXInT_1624177607.png!avatar200" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">25</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">3</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/project/"><i class="fa-fw fas fa-images"></i><span> 项目</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fa fa-paper-plane"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Justic</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/project/"><i class="fa-fw fas fa-images"></i><span> 项目</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fa fa-paper-plane"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Vue 路由</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-07-13T12:05:37.000Z" title="发表于 2022-07-13 20:05:37">2022-07-13</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-07-21T08:33:22.987Z" title="更新于 2022-07-21 16:33:22">2022-07-21</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Vue/">Vue</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">30.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>133分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Vue 路由"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span><span class="post-meta-separator">|</span><span class="post-meta-commentcount"><i class="far fa-comments fa-fw post-meta-icon"></i><span class="post-meta-label">评论数:</span><a href="/2022/07/13/Vue/Vue%20Router/vueRouter/#post-comment" itemprop="discussionUrl"><span class="valine-comment-count" data-xid="/2022/07/13/Vue/Vue%20Router/vueRouter/" itemprop="commentCount"><i class="fa-solid fa-spinner fa-spin"></i></span></a></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="Vue-Router"><a href="#Vue-Router" class="headerlink" title="Vue Router"></a>Vue Router</h1><h1 id="一、Vue-Router-介绍"><a href="#一、Vue-Router-介绍" class="headerlink" title="一、Vue Router 介绍"></a>一、Vue Router 介绍</h1><h2 id="1、路由简介"><a href="#1、路由简介" class="headerlink" title="1、路由简介"></a>1、路由简介</h2><p>路由是一个比较广义和抽象的概念，路由的本质就是<strong>对应关系</strong>。</p>
<p>在开发中，路由分为：</p>
<ul>
<li>后端路由</li>
<li>前端路由</li>
</ul>
<p><strong>后端路由</strong></p>
<ul>
<li>概念：根据不同的用户 URL 请求，返回不同的内容</li>
<li>本质：URL 请求地址与服务器资源之间的对应关系</li>
</ul>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E5%90%8E%E7%AB%AF%E8%B7%AF%E7%94%B1.png"></p>
<p><strong>SPA（Single Page Application）</strong></p>
<ul>
<li>Ajax 前端渲染（前端渲染提高性能，但是不支持浏览器的前进后退操作）</li>
<li>SPA（Single Page Application）单页面应用程序：整个网站只有一个页面，内 容的变化通过 Ajax 局部更新实现、同时支持浏览器地址栏的前进和后退操作</li>
<li>SPA 实现原理之一：基于 URL 地址的 hash（hash 的变化会导致浏览器记录访问历 史的变化、但是 hash 的变化不会触发新的 URL 请求</li>
<li>在实现 SPA 过程中，最核心的技术点就是前端路由</li>
</ul>
<p><strong>前端路由</strong></p>
<ul>
<li>概念：根据不同的用户事件，显示不同的页面内容</li>
<li>本质：用户事件与事件处理函数之间的对应关系</li>
</ul>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E5%89%8D%E7%AB%AF%E8%B7%AF%E7%94%B1.png"></p>
<h2 id="2、实现简易前端路由"><a href="#2、实现简易前端路由" class="headerlink" title="2、实现简易前端路由"></a>2、实现简易前端路由</h2><p>基于 URL 中的 hash 实现（点击菜单的时候改变 URL 的 hash，根据 hash 的变化控制组件的切换）</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E5%9F%BA%E6%9C%AC%E6%A1%88%E4%BE%8B.png"></p>
<p>案例代码实现如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vue 实例控制的 div 区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 切换组件的超链接 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#/zhuye&quot;</span>&gt;</span>主页<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#/keji&quot;</span>&gt;</span>科技<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#/caijing&quot;</span>&gt;</span>财经<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#/yule&quot;</span>&gt;</span>娱乐<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 根据 :is 属性指定的组件名称，把对应的组件渲染到 component 标签所在的位置 --&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 可以把 component 标签当做是【组件的占位符】 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">component</span> <span class="attr">:is</span>=<span class="string">&quot;comName&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">component</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// #region 定义需要被切换的 4 个组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 主页组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> zhuye = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;主页信息&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 科技组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> keji = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;科技信息&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 财经组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> caijing = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;财经信息&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 娱乐组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> yule = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;娱乐信息&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// #endregion</span></span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// #region vue 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">comName</span>: <span class="string">&quot;zhuye&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 注册私有组件</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          zhuye,</span></span><br><span class="line"><span class="language-javascript">          keji,</span></span><br><span class="line"><span class="language-javascript">          caijing,</span></span><br><span class="line"><span class="language-javascript">          yule,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// #endregion</span></span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 监听 window 的 onhashchange 事件，根据获取到的最新的 hash 值，切换要显示的组件的名称</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">window</span>.<span class="property">onhashchange</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 通过 location.hash 获取到最新的 hash 值</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">console</span>.<span class="title function_">log</span>(location.<span class="property">hash</span>);</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">switch</span> (location.<span class="property">hash</span>.<span class="title function_">slice</span>(<span class="number">1</span>)) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">case</span> <span class="string">&quot;/zhuye&quot;</span>:</span></span><br><span class="line"><span class="language-javascript">            vm.<span class="property">comName</span> = <span class="string">&quot;zhuye&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">break</span>;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">case</span> <span class="string">&quot;/keji&quot;</span>:</span></span><br><span class="line"><span class="language-javascript">            vm.<span class="property">comName</span> = <span class="string">&quot;keji&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">break</span>;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">case</span> <span class="string">&quot;/caijing&quot;</span>:</span></span><br><span class="line"><span class="language-javascript">            vm.<span class="property">comName</span> = <span class="string">&quot;caijing&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">break</span>;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">case</span> <span class="string">&quot;/yule&quot;</span>:</span></span><br><span class="line"><span class="language-javascript">            vm.<span class="property">comName</span> = <span class="string">&quot;yule&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">break</span>;</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="3、vue-router的基本使用"><a href="#3、vue-router的基本使用" class="headerlink" title="3、vue-router的基本使用"></a>3、<code>vue-router</code>的基本使用</h2><p><code>Vue Router</code>（官网：<code>https://router.vuejs.org/zh/</code>）是 <code>Vue.js</code> 官方的路由管理器。 它和<code> Vue.js</code> 的核心深度集成，可以非常方便的用于<code>SPA</code>应用程序的开发。</p>
<p>基本使用的步骤：</p>
<ol>
<li>引入相关的库文件</li>
<li>添加路由链接</li>
<li>添加路由填充位</li>
<li>定义路由组件</li>
<li>配置路由规则并创建路由实例</li>
<li>把路由挂载到<code> Vue</code> 根实例中</li>
</ol>
<p>下面看一下具体的实施过程</p>
<ol>
<li>引入相关的库文件</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;!-- 导入 vue 文件，为全局 <span class="variable language_">window</span> 对象挂载 <span class="title class_">Vue</span> 构造函数 --&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line">&lt;!-- 导入 vue-router 文件，为全局 <span class="variable language_">window</span> 对象挂载 <span class="title class_">VueRouter</span> 构造函数 --&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>添加路由链接</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;!-- router-link 是 vue 中提供的标签，默认会被渲染为 a 标签 --&gt;</span><br><span class="line">&lt;!-- to 属性默认会被渲染为 href 属性 --&gt;</span><br><span class="line">&lt;!-- to 属性的值默认会被渲染为 # 开头的 hash 地址 --&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user&quot;</span>&gt;</span>User<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<ol start="3">
<li>添加路由填充位</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;!-- 路由填充位（也叫做路由占位符） --&gt;</span><br><span class="line">&lt;!-- 将来通过路由规则匹配到的组件，将会被渲染到 router-view 所在的位置 --&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<ol start="4">
<li>定义路由组件</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;User&lt;/div&gt;&quot;</span>,</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">var</span> <span class="title class_">Register</span> = &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;Register&lt;/div&gt;&quot;</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ol start="5">
<li>配置路由规则并创建路由实例</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建路由实例对象</span></span><br><span class="line"><span class="keyword">var</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="comment">// routes 是路由规则数组</span></span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    <span class="comment">// 每个路由规则都是一个配置对象，其中至少包含 path 和 component 两个属性：</span></span><br><span class="line">    <span class="comment">// path 表示当前路由规则匹配的 hash 地址</span></span><br><span class="line">    <span class="comment">// component 表示当前路由规则对应要展示的组件</span></span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<ol start="6">
<li>把路由挂载到 Vue 根实例中</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">  <span class="comment">// 为了能够让路由规则生效，必须把路由对象挂载到 vue 实例对象上</span></span><br><span class="line">  router,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>完整代码实现如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user&quot;</span>&gt;</span>User<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;User 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="4、路由重定向"><a href="#4、路由重定向" class="headerlink" title="4、路由重定向"></a>4、路由重定向</h2><p>路由重定向指的是：用户在访问地址 A 的时候，强制用户跳转到地址 C ，从而展示特定的组件页面；</p>
<p>通过路由规则的 redirect 属性，指定一个新的路由地址，可以很方便地设置路由的重定向：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    <span class="comment">// 其中，path 表示需要被重定向的原地址，redirect 表示将要被重定向到的新地址</span></span><br><span class="line">    <span class="comment">//当用户在地址栏中输入`/`,会自动的跳转到`/user`,而`/user`对应的组件为User</span></span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>具体实现的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user&quot;</span>&gt;</span>User<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;User 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//路由重定向</span></span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="5、嵌套路由"><a href="#5、嵌套路由" class="headerlink" title="5、嵌套路由"></a>5、嵌套路由</h2><p><strong>嵌套路由功能分析</strong></p>
<p>点击父级路由链接显示模板内容</p>
<p>模板内容中又有子级路由链接</p>
<p>点击子级路由链接显示子级模板内容</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E5%B5%8C%E5%A5%97%E8%B7%AF%E7%94%B1.png"></p>
<p>下面看一下实现的步骤</p>
<p><strong>父路由组件模板</strong></p>
<ul>
<li>父级路由链接</li>
<li>父组件路由填充位</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt; </span><br><span class="line">      &lt;router-link to=&quot;/user&quot;&gt;User&lt;/router-link&gt; </span><br><span class="line">      &lt;router-link to=&quot;/register&quot;&gt;Register&lt;/router-link&gt; </span><br><span class="line"> &lt;/p&gt;</span><br><span class="line">&lt;div&gt;      </span><br><span class="line">        &lt;!-- 控制组件的显示位置 --&gt;       </span><br><span class="line">        &lt;router-view&gt;&lt;/router-view&gt; </span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>以上的内容，在前面的课程中已经实现。</p>
<p><strong>子级路由模板</strong></p>
<ul>
<li>子级路由链接</li>
<li>子级路由填充位</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;    </span></span><br><span class="line"><span class="string">			&lt;h1&gt;Register 组件&lt;/h1&gt;     </span></span><br><span class="line"><span class="string">			&lt;hr/&gt; </span></span><br><span class="line"><span class="string">      &lt;router-link to=&quot;/register/tab1&quot;&gt;Tab1&lt;/router-link&gt; </span></span><br><span class="line"><span class="string">      &lt;router-link to=&quot;/register/tab2&quot;&gt;Tab2&lt;/router-link&gt;  </span></span><br><span class="line"><span class="string">      &lt;!-- 子路由填充位置 --&gt;       </span></span><br><span class="line"><span class="string">		&lt;router-view/&gt; </span></span><br><span class="line"><span class="string">    &lt;/div&gt;`</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p><strong>嵌套路由配置</strong></p>
<p>父级路由通过<code>children</code>属性配置子级路由</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">Register</span>,</span><br><span class="line">      <span class="comment">// 通过 children 属性，为 /register 添加子路由规则</span></span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/register/tab1&quot;</span>, <span class="attr">component</span>: <span class="title class_">Tab1</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/register/tab2&quot;</span>, <span class="attr">component</span>: <span class="title class_">Tab2</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>具体代码实现如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user&quot;</span>&gt;</span>User<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const User = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: &quot;<span class="tag">&lt;<span class="name">h1</span>&gt;</span>User 组件<span class="tag">&lt;/<span class="name">h1</span>&gt;</span>&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //修改Register组件</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Register = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Register 组件<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">hr</span>/&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 子路由链接 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register/tab1&quot;</span>&gt;</span>tab1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register/tab2&quot;</span>&gt;</span>tab2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 子路由的占位符 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">router-view</span> /&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Tab1 = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: &quot;<span class="tag">&lt;<span class="name">h3</span>&gt;</span>tab1 子组件<span class="tag">&lt;/<span class="name">h3</span>&gt;</span>&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Tab2 = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: &quot;<span class="tag">&lt;<span class="name">h3</span>&gt;</span>tab2 子组件<span class="tag">&lt;/<span class="name">h3</span>&gt;</span>&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // 创建路由实例对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const router = new VueRouter(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // 所有的路由规则</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        routes: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123; path: &quot;/&quot;, redirect: &quot;/user&quot; &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123; path: &quot;/user&quot;, component: User &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          // children 数组表示子路由规则</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            path: &quot;/register&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            component: Register,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/register/tab1&quot;, component: Tab1 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/register/tab2&quot;, component: Tab2 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // 指定控制的区域</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;&#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // router: router</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        router,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="6、动态路由匹配"><a href="#6、动态路由匹配" class="headerlink" title="6、动态路由匹配"></a>6、动态路由匹配</h2><h3 id="6-1-动态匹配路由的基本用法"><a href="#6-1-动态匹配路由的基本用法" class="headerlink" title="6.1 动态匹配路由的基本用法"></a>6.1 动态匹配路由的基本用法</h3><p>思考：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line">&lt;!– 有如下 3 个路由链接 --&gt;</span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/3&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 定义如下三个对应的路由规则，是否可行？？？</span></span><br><span class="line">&#123; <span class="attr">path</span>: <span class="string">&#x27;/user/1&#x27;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;</span><br><span class="line">&#123; <span class="attr">path</span>: <span class="string">&#x27;/user/2&#x27;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;</span><br><span class="line">&#123; <span class="attr">path</span>: <span class="string">&#x27;/user/3&#x27;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;</span><br></pre></td></tr></table></figure>

<p>虽然以上规则可以匹配成功，但是这样写比较麻烦。如果有 100 个规则，那么写起来就会非常的麻烦。</p>
<p>通过观察，可以发现整个路由规则中只有后续的数字是在变化的。所以这里可以通过动态路由参数的模式进行路由匹配。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    <span class="comment">// 动态路径参数 以冒号开头</span></span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">  <span class="comment">// 路由组件中通过$route.params获取路由参数</span></span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;User &#123;&#123; $route.params.id &#125;&#125;&lt;/div&gt;&quot;</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>具体代码实现如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/3&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;$route.params.id&#125;&#125;&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="6-2-路由组件传递参数"><a href="#6-2-路由组件传递参数" class="headerlink" title="6.2 路由组件传递参数"></a>6.2 路由组件传递参数</h3><p><code>$route</code>与对应路由形成高度耦合，不够灵活，所以可以使用<code>props</code>将组件和路由解耦</p>
<p>第一种情况：</p>
<p><strong>props 的值为布尔类型</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    <span class="comment">// 如果 props 被设置为 true，route.params 将会被设置为组件属性</span></span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>], <span class="comment">// 使用 props 接收路由参数</span></span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;用户ID：&#123;&#123; id &#125;&#125;&lt;/div&gt;&quot;</span>, <span class="comment">// 使用路由参数</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在定义路由规则的时候，为其添加了<code>props</code>属性，并将其值设置为<code>true</code>.那么在组件中就可以通过<code>props:[&#39;id&#39;]</code>的形式来获取对应的参数值。</p>
<p>具体代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/3&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>], <span class="comment">//获取id的值。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;id&#125;&#125;&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//将props设置为true.</span></span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">User</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>第二种情况： <code>props</code>的值为对象类型</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"> <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">    <span class="attr">routes</span>: [</span><br><span class="line">        <span class="comment">// 如果 props 是一个对象，它会被按原样设置为组件属性</span></span><br><span class="line">        <span class="comment">//这里相当于给组件User,通过路由的形式传递了一个对象，而这时候id在User组件中就无法获取到了。</span></span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&#x27;/user/:id&#x27;</span>, <span class="attr">component</span>: <span class="title class_">User</span>, <span class="attr">props</span>: &#123; <span class="attr">uname</span>: <span class="string">&#x27;lisi&#x27;</span>, <span class="attr">age</span>: <span class="number">12</span> &#125;&#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">    <span class="attr">props</span>: [<span class="string">&#x27;uname&#x27;</span>, <span class="string">&#x27;age&#x27;</span>],</span><br><span class="line">      <span class="attr">template</span>: ‘&lt;div&gt;用户信息：&#123;&#123; uname + <span class="string">&#x27;---&#x27;</span> + age&#125;&#125;&lt;/div&gt;<span class="string">&#x27;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>

<p>具体代码实现如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/3&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>, <span class="string">&quot;uname&quot;</span>, <span class="string">&quot;age&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>:</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;&lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;id&#125;&#125; -- 姓名为:&#123;&#123;uname&#125;&#125; -- 年龄为：&#123;&#123;age&#125;&#125;&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">component</span>: <span class="title class_">User</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">props</span>: &#123; <span class="attr">uname</span>: <span class="string">&quot;lisi&quot;</span>, <span class="attr">age</span>: <span class="number">20</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，在路由规则中，通过<code>props</code>向用户组件中传递了一个对象，那么在<code>User</code>用户组件中可以接收到传递过来的对象。但是参数<code>id</code>无法接收到。</p>
<p>如果要解决这个问题，可以使用<code>props</code>的值为函数类型。也就是给<code>props</code>传递一个函数。</p>
<p><strong>第三种情况：<code>props</code>的值为函数类型</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">    <span class="attr">routes</span>: [</span><br><span class="line">        <span class="comment">// 如果 props 是一个函数，则这个函数接收 route 对象为自己的形参</span></span><br><span class="line">        <span class="comment">//route就是参数对象。</span></span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&#x27;/user/:id&#x27;</span>,</span><br><span class="line">        <span class="attr">component</span>: <span class="title class_">User</span>,</span><br><span class="line">        <span class="attr">props</span>: <span class="function"><span class="params">route</span> =&gt;</span> (&#123; <span class="attr">uname</span>: <span class="string">&#x27;zs&#x27;</span>, <span class="attr">age</span>: <span class="number">20</span>, <span class="attr">id</span>: route.<span class="property">params</span>.<span class="property">id</span> &#125;)&#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">    <span class="attr">props</span>: [<span class="string">&#x27;uname&#x27;</span>, <span class="string">&#x27;age&#x27;</span>, <span class="string">&#x27;id&#x27;</span>],</span><br><span class="line">      <span class="attr">template</span>: ‘&lt;div&gt;用户信息：&#123;&#123; uname + <span class="string">&#x27;---&#x27;</span> + age + <span class="string">&#x27;---&#x27;</span> + id&#125;&#125;&lt;/div&gt;<span class="string">&#x27;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>

<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/3&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>, <span class="string">&quot;uname&quot;</span>, <span class="string">&quot;age&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>:</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;&lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;id&#125;&#125; -- 姓名为:&#123;&#123;uname&#125;&#125; -- 年龄为：&#123;&#123;age&#125;&#125;&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">component</span>: <span class="title class_">User</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">props</span>: <span class="function">(<span class="params">route</span>) =&gt;</span> (&#123; <span class="attr">uname</span>: <span class="string">&quot;zs&quot;</span>, <span class="attr">age</span>: <span class="number">20</span>, <span class="attr">id</span>: route.<span class="property">params</span>.<span class="property">id</span> &#125;),</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="7、命名路由"><a href="#7、命名路由" class="headerlink" title="7、命名路由"></a>7、命名路由</h2><p>为了更加方便的表示路由的路径，可以给路由规则起一个别名，即为“命名路由”。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&quot;user&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">User</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!--单击链接，可以跳转到名称为`user`的这个路由规则，并且通过params进行参数的传递--&gt;</span><br><span class="line">&lt;router-link :to=&quot;&#123; name: &#x27;user&#x27;, params: &#123; id: 123 &#125; &#125;&quot;&gt;User&lt;/router-link&gt;</span><br></pre></td></tr></table></figure>

<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 导入 vue 文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue_2.5.22.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue-router_3.0.2.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 被 vm 实例所控制的区域 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/1&quot;</span>&gt;</span>User1<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/user/2&quot;</span>&gt;</span>User2<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!--单击链接，可以跳转到名称为`user`的这个路由规则，并且通过params进行参数的传递,id一定要和路由规则中定义的参数保持一致--&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">:to</span>=<span class="string">&quot;&#123; name: &#x27;user&#x27;, params: &#123;id: 3&#125; &#125;&quot;</span>&gt;</span>User3<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/register&quot;</span>&gt;</span>Register<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 路由占位符 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>, <span class="string">&quot;uname&quot;</span>, <span class="string">&quot;age&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>:</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;&lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;id&#125;&#125; -- 姓名为:&#123;&#123;uname&#125;&#125; -- 年龄为：&#123;&#123;age&#125;&#125;&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">Register</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;h1&gt;Register 组件&lt;/h1&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 所有的路由规则</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">routes</span>: [</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">redirect</span>: <span class="string">&quot;/user&quot;</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// 命名路由</span></span></span><br><span class="line"><span class="language-javascript">            <span class="attr">name</span>: <span class="string">&quot;user&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">path</span>: <span class="string">&quot;/user/:id&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">component</span>: <span class="title class_">User</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">props</span>: <span class="function">(<span class="params">route</span>) =&gt;</span> (&#123; <span class="attr">uname</span>: <span class="string">&quot;zs&quot;</span>, <span class="attr">age</span>: <span class="number">20</span>, <span class="attr">id</span>: route.<span class="property">params</span>.<span class="property">id</span> &#125;),</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">component</span>: <span class="title class_">Register</span> &#125;,</span></span><br><span class="line"><span class="language-javascript">        ],</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 创建 vm 实例对象</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 指定控制的区域</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 挂载路由实例对象</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// router: router</span></span></span><br><span class="line"><span class="language-javascript">        router,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="8、编程式导航"><a href="#8、编程式导航" class="headerlink" title="8、编程式导航"></a>8、编程式导航</h2><p><strong>页面导航的两种方式</strong></p>
<p>声明式导航：通过点击链接实现导航的方式，叫做声明式导航<br>例如：普通网页中的 <code>&lt;a&gt;&lt;/a&gt;</code> 链接 或 vue 中的 <code>&lt;router-link&gt;&lt;/router-link&gt;</code><br>编程式导航：通过调用<code>JavaScript</code>形式的<code>API</code>实现导航的方式，叫做编程式导航<br>例如：普通网页中的 <code>location.href </code></p>
<p><strong>编程式导航基本用法</strong></p>
<p>常用的编程式导航 API 如下：</p>
<p><code>this.$router.push</code>(‘hash 地址’)</p>
<p><code>this.$router.go(n)</code></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">User</span> = &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;&lt;button @click=&quot;goRegister&quot;&gt;跳转到注册页面&lt;/button&gt;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="attr">goRegister</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">// 用编程的方式控制路由跳转</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="string">&quot;/register&quot;</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>具体吗实现：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot; /&gt;</span><br><span class="line">    &lt;title&gt;Document&lt;/title&gt;</span><br><span class="line">    &lt;!-- 导入 vue 文件 --&gt;</span><br><span class="line">    &lt;script src=&quot;./lib/vue_2.5.22.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script src=&quot;./lib/vue-router_3.0.2.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;!-- 被 vm 实例所控制的区域 --&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;router-link to=&quot;/user/1&quot;&gt;User1&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link to=&quot;/user/2&quot;&gt;User2&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link :to=&quot;&#123; name: &#x27;user&#x27;, params: &#123; id: 3 &#125; &#125;&quot;&gt;User3&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link to=&quot;/register&quot;&gt;Register&lt;/router-link&gt;</span><br><span class="line"></span><br><span class="line">      &lt;!-- 路由占位符 --&gt;</span><br><span class="line">      &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const User = &#123;</span><br><span class="line">        props: [&quot;id&quot;, &quot;uname&quot;, &quot;age&quot;],</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">          &lt;h1&gt;User 组件 -- 用户id为: &#123;&#123;id&#125;&#125; -- 姓名为:&#123;&#123;uname&#125;&#125; -- 年龄为：&#123;&#123;age&#125;&#125;&lt;/h1&gt;</span><br><span class="line">          &lt;button @click=&quot;goRegister&quot;&gt;跳转到注册页面&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;`,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          goRegister() &#123;</span><br><span class="line">            this.$router.push(&quot;/register&quot;); //编程式导航</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;;</span><br><span class="line"></span><br><span class="line">      const Register = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">          &lt;h1&gt;Register 组件&lt;/h1&gt;</span><br><span class="line">          &lt;button @click=&quot;goBack&quot;&gt;后退&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;`,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          goBack() &#123;</span><br><span class="line">            this.$router.go(-1);</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;;</span><br><span class="line"></span><br><span class="line">      // 创建路由实例对象</span><br><span class="line">      const router = new VueRouter(&#123;</span><br><span class="line">        // 所有的路由规则</span><br><span class="line">        routes: [</span><br><span class="line">          &#123; path: &quot;/&quot;, redirect: &quot;/user&quot; &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            // 命名路由</span><br><span class="line">            name: &quot;user&quot;,</span><br><span class="line">            path: &quot;/user/:id&quot;,</span><br><span class="line">            component: User,</span><br><span class="line">            props: (route) =&gt; (&#123; uname: &quot;zs&quot;, age: 20, id: route.params.id &#125;),</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123; path: &quot;/register&quot;, component: Register &#125;,</span><br><span class="line">        ],</span><br><span class="line">      &#125;);</span><br><span class="line"></span><br><span class="line">      // 创建 vm 实例对象</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        // 指定控制的区域</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">        // 挂载路由实例对象</span><br><span class="line">        // router: router</span><br><span class="line">        router,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p><strong>router.push() 方法的参数规则</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 字符串(路径名称)</span></span><br><span class="line">router.<span class="title function_">push</span>(<span class="string">&quot;/home&quot;</span>);</span><br><span class="line"><span class="comment">// 对象</span></span><br><span class="line">router.<span class="title function_">push</span>(&#123; <span class="attr">path</span>: <span class="string">&quot;/home&quot;</span> &#125;);</span><br><span class="line"><span class="comment">// 命名的路由(传递参数)</span></span><br><span class="line">router.<span class="title function_">push</span>(&#123; <span class="attr">name</span>: <span class="string">&quot;/user&quot;</span>, <span class="attr">params</span>: &#123; <span class="attr">userId</span>: <span class="number">123</span> &#125; &#125;);</span><br><span class="line"><span class="comment">// 带查询参数，变成 /register?uname=lisi</span></span><br><span class="line">router.<span class="title function_">push</span>(&#123; <span class="attr">path</span>: <span class="string">&quot;/register&quot;</span>, <span class="attr">query</span>: &#123; <span class="attr">uname</span>: <span class="string">&quot;lisi&quot;</span> &#125; &#125;);</span><br></pre></td></tr></table></figure>

<h2 id="9、路由案例"><a href="#9、路由案例" class="headerlink" title="9、路由案例"></a>9、路由案例</h2><h3 id="9-1-抽离并且渲染App根组件。"><a href="#9-1-抽离并且渲染App根组件。" class="headerlink" title="9.1 抽离并且渲染App根组件。"></a>9.1 抽离并且渲染<code>App</code>根组件。</h3><p>将素材中的代码修改成如下的形式：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>基于vue-router的案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue-router/dist/vue-router.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">html</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">body</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-id">#app</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.header</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">24px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.footer</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#888</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">display</span>: flex;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">1</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> <span class="selector-tag">a</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: white;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-decoration</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.right</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">5px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.btns</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: left;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding-left</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">box-sizing</span>: border-box;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">button</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">30px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ecf5ff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid lightskyblue;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main-content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin-top</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">list-style</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> <span class="selector-tag">li</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#a0a0a0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">cursor</span>: pointer;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-bottom</span>: <span class="number">1px</span> solid <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">table</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-collapse</span>: collapse;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">td</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#eee</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const App = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 头部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">header</span> <span class="attr">class</span>=<span class="string">&quot;header&quot;</span>&gt;</span>传智后台管理系统<span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 中间主体区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 左侧菜单栏 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content left&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span>用户管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span>权限管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span>商品管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span>订单管理<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span>系统设置<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 右侧内容区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content right&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main-content&quot;</span>&gt;</span>添加用户表单<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 尾部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">footer</span> <span class="attr">class</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>版权信息<span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //创建路由对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const router = new VueRouter(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        routes: [&#123; path: &quot;/&quot;, component: App &#125;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        router,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们导入了<code>Vue</code>与<code>Vue-Router</code>的文件。</p>
<p>然后将核心内容定义到<code>App</code>这个组件中，同时创建了路由对象，并且指定了路由的规则。接下来将路由对象挂载到了<code>Vue</code>的实例中。</p>
<p>同时在<code>&lt;div id=&#39;app&#39;&gt;&lt;/div&gt;</code>中使用<code>router-view</code>定义了一个占位符。当输入的地址为<code>/</code>,对应的<code>App</code>组件就会在该占位符中进行展示。</p>
<h3 id="9-2-将菜单改造为路由连接"><a href="#9-2-将菜单改造为路由连接" class="headerlink" title="9.2 将菜单改造为路由连接"></a>9.2 将菜单改造为路由连接</h3><p>将模板中的菜单修改成路由连接的形式，如下所示：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 左侧菜单栏 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content left&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/users&quot;</span>&gt;</span> 用户管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/rights&quot;</span>&gt;</span> 权限管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/goods&quot;</span>&gt;</span> 商品管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/orders&quot;</span>&gt;</span> 订单管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/settings&quot;</span>&gt;</span> 系统设置<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="9-3-创建菜单对应组件"><a href="#9-3-创建菜单对应组件" class="headerlink" title="9.3 创建菜单对应组件"></a>9.3 创建菜单对应组件</h3><p>基本组件创建如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">const Users = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;用户管理区域&lt;/h3&gt;</span><br><span class="line">        </span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">`, &#125;; const Rights = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;权限管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">`, &#125;; const Goods = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;商品管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">`, &#125;; const Orders = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;订单管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">`, &#125;; const Settings = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;系统设置区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">`, &#125;;</span><br></pre></td></tr></table></figure>

<p>我们知道，当单击左侧的菜单时，上面定义的组件将会在右侧进行展示。</p>
<p>所以需要在右侧，添加一个<code>router-view</code>的占位符。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!-- 右侧内容区域 --&gt;</span><br><span class="line">       &lt;div class=&quot;content right&quot;&gt;&lt;div class=&quot;main-content&quot;&gt; &lt;router-view /&gt;&lt;/div&gt;&lt;/div&gt;</span><br></pre></td></tr></table></figure>

<h3 id="9-4-添加子路由规则并实现路由重定向"><a href="#9-4-添加子路由规则并实现路由重定向" class="headerlink" title="9.4 添加子路由规则并实现路由重定向"></a>9.4 添加子路由规则并实现路由重定向</h3><p>在上一小节中，我们已经将组件都定义好了，下面需要定义其对应的路由规则。</p>
<p>怎样添加对应的路由规则呢？</p>
<p>我们知道整个页面是<code>App</code>根组件渲染出来的，而前面定义的组件，都是在<code>App</code>根组件中进行渲染的,也就是作为了<code>App</code>组件的子组件。</p>
<p>所以，为上一小节中创建的组件添加路由规则，应该是作为<code>App</code>的子路由来进行添加，这样对应的组件才会在<code>App</code>组件中进行渲染。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">App</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/users&quot;</span>, <span class="attr">component</span>: <span class="title class_">Users</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/rights&quot;</span>, <span class="attr">component</span>: <span class="title class_">Rights</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/goods&quot;</span>, <span class="attr">component</span>: <span class="title class_">Goods</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/orders&quot;</span>, <span class="attr">component</span>: <span class="title class_">Orders</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/settings&quot;</span>, <span class="attr">component</span>: <span class="title class_">Settings</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>当用户在浏览器的地址栏中输入’&#x2F;‘的时候，会渲染<code>App</code>组件，同时会重定向到<code>/users</code>，从而将<code>Users</code>组件渲染出来，而<code>Users</code>组件是在整个<code>App</code>组件的右侧进行渲染展示。</p>
<p>当点击左侧的菜单时，对应的组件会在右侧进行展示。</p>
<h3 id="9-5-渲染用户列表数据"><a href="#9-5-渲染用户列表数据" class="headerlink" title="9.5 渲染用户列表数据"></a>9.5 渲染用户列表数据</h3><p>这里将用户组件的内容修改成如下形式：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">const Users = &#123; data() &#123; return &#123; userlist: [ &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span><br><span class="line">&#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;, &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;, &#123; id: 4,</span><br><span class="line">name: &quot;赵六&quot;, age: 40 &#125;, ], &#125;; &#125;, template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;用户管理区域&lt;/h3&gt;</span><br><span class="line">        &lt;table&gt;</span><br><span class="line">          &lt;thead&gt;</span><br><span class="line">            &lt;tr&gt;&lt;th&gt;编号&lt;/th&gt;&lt;th&gt;姓名&lt;/th&gt;&lt;th&gt;年龄&lt;/th&gt;&lt;th&gt;操作&lt;/th&gt;&lt;/tr&gt;</span><br><span class="line">          &lt;/thead&gt;</span><br><span class="line">          &lt;tbody&gt;</span><br><span class="line">            &lt;tr v-for=&quot;item in userlist&quot; :key=&quot;item.id&quot;&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.id&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.name&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.age&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;</span><br><span class="line">                &lt;a href=&quot;javascript:;&quot;&gt;详情&lt;/a&gt;</span><br><span class="line">              &lt;/td&gt;</span><br><span class="line">            &lt;/tr&gt;</span><br><span class="line">          &lt;/tbody&gt;</span><br><span class="line">        &lt;/table&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">`, &#125;;</span><br></pre></td></tr></table></figure>

<p>在<code>Users</code>组件中定义用户数据，并且在模板中通过循环的方式将数据渲染出来。</p>
<h3 id="9-6-跳转到详情页"><a href="#9-6-跳转到详情页" class="headerlink" title="9.6 跳转到详情页"></a>9.6 跳转到详情页</h3><p>当单击”详情”链接时，跳转到对应的详情页面。这里需要用到编程式导航的内容。</p>
<p>首先定义用户详情页组件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//用户详情组件</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">UserInfo</span> = &#123;</span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;id&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;</span></span><br><span class="line"><span class="string">          &lt;h5&gt;用户详情页 --- 用户Id为：&#123;&#123;id&#125;&#125;&lt;/h5&gt;</span></span><br><span class="line"><span class="string">          &lt;button @click=&quot;goback()&quot;&gt;后退&lt;/button&gt;</span></span><br><span class="line"><span class="string">        &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">goback</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">// 实现后退功能</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">go</span>(-<span class="number">1</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在该组件中通过<code>props</code>方式接收传递过来的的用户编号，并且将其打印出来。</p>
<p>同时在该组件中添加一个后退的按钮，通过编程式导航的方式实现后退。</p>
<p>对应的路由规则如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">App</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/users&quot;</span>, <span class="attr">component</span>: <span class="title class_">Users</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/userinfo/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">UserInfo</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/rights&quot;</span>, <span class="attr">component</span>: <span class="title class_">Rights</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/goods&quot;</span>, <span class="attr">component</span>: <span class="title class_">Goods</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/orders&quot;</span>, <span class="attr">component</span>: <span class="title class_">Orders</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/settings&quot;</span>, <span class="attr">component</span>: <span class="title class_">Settings</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>当输入的地址为:’&#x2F;userinfo&#x2F;5’的形式是会渲染<code>UserInfo</code>这个组件，同时将<code>props</code>设置为<code>true</code>,表示会传递对应的<code>id</code>值。</p>
<p><code>UserInfo</code>这个组件也是<code>App</code>组件的子组件，对应的也会在<code>App</code>组件的右侧进行展示。</p>
<p>同时，在<code>Users</code>组件中，给“详情”链接添加对应的单击事件，</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line">const Users = &#123; data() &#123; return &#123; userlist: [ &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span><br><span class="line">&#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;, &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;, &#123; id: 4,</span><br><span class="line">name: &quot;赵六&quot;, age: 40 &#125;, ], &#125;; &#125;, methods: &#123; goDetail(id) &#123; console.log(id);</span><br><span class="line">this.$router.push(&quot;/userinfo/&quot; + id); &#125;, &#125;, template: `</span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h3</span>&gt;</span>用户管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">th</span>&gt;</span>编号<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">th</span>&gt;</span>姓名<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">th</span>&gt;</span>年龄<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">th</span>&gt;</span>操作<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">tr</span> <span class="attr">v-for</span>=<span class="string">&quot;item in userlist&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>&#123;&#123;item.id&#125;&#125;<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>&#123;&#123;item.name&#125;&#125;<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>&#123;&#123;item.age&#125;&#125;<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;goDetail(item.id)&quot;</span>&gt;</span>详情<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">`, &#125;;</span><br></pre></td></tr></table></figure>

<p>对应<code>goDetail</code>方法中，通过编程式导航跳转到用户详情页面。</p>
<p>完整代码案例：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>基于vue-router的案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue-router/dist/vue-router.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">html</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">body</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-id">#app</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.header</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">24px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.footer</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#888</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">display</span>: flex;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">1</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> <span class="selector-tag">a</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: white;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-decoration</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.right</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">5px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.btns</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: left;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding-left</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">box-sizing</span>: border-box;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">button</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">30px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ecf5ff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid lightskyblue;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main-content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin-top</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">list-style</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> <span class="selector-tag">li</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#a0a0a0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">cursor</span>: pointer;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-bottom</span>: <span class="number">1px</span> solid <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">table</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-collapse</span>: collapse;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">td</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#eee</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const App = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 头部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">header</span> <span class="attr">class</span>=<span class="string">&quot;header&quot;</span>&gt;</span>传智后台管理系统<span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 中间主体区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 左侧菜单栏 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content left&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/users&quot;</span>&gt;</span> 用户管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/rights&quot;</span>&gt;</span> 权限管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/goods&quot;</span>&gt;</span> 商品管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/orders&quot;</span>&gt;</span> 订单管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/settings&quot;</span>&gt;</span> 系统设置<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 右侧内容区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content right&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main-content&quot;</span>&gt;</span> <span class="tag">&lt;<span class="name">router-view</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="comment">&lt;!-- 尾部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;<span class="name">footer</span> <span class="attr">class</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>版权信息<span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Users = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          return &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            userlist: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 4, name: &quot;赵六&quot;, age: 40 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goDetail(id) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            console.log(id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.push(&quot;/userinfo/&quot; + id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>用户管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">tr</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>编号<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>姓名<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>年龄<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>操作<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">tr</span> <span class="attr">v-for</span>=<span class="string">&quot;item in userlist&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.name</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.age</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;goDetail(item.id)&quot;</span>&gt;</span>详情<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //用户详情组件</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const UserInfo = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;id&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h5</span>&gt;</span>用户详情页 --- 用户Id为：</span><span class="template-variable">&#123;&#123;<span class="name">id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;goback()&quot;</span>&gt;</span>后退<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goback() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // 实现后退功能</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.go(-1);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Rights = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>权限管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Goods = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>商品管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Orders = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>订单管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Settings = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">h3</span>&gt;</span>系统设置区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // 创建路由对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const router = new VueRouter(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        routes: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            path: &quot;/&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            component: App,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            redirect: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/users&quot;, component: Users &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        router,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="10、路由守卫"><a href="#10、路由守卫" class="headerlink" title="10、路由守卫"></a>10、路由守卫</h2><p><code>Vue-router</code>中的路由守卫，主要是对其内容进行保护，如果没有对应的权限，则不允许访问。</p>
<p>我们首先来看一下全局守卫，也就是所有的路由都会经过全局守卫来进行检测。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//实现全局守卫</span></span><br><span class="line">router.<span class="title function_">beforeEach</span>(<span class="function">(<span class="params">to, <span class="keyword">from</span>, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">//to:去哪个页面，from来自哪个页面，next继续执行.</span></span><br><span class="line">  <span class="comment">//判断哪个路由需要进行守卫，这里可以通过元数据方式</span></span><br><span class="line">  <span class="keyword">if</span> (to.<span class="property">meta</span>.<span class="property">auth</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">isLogin</span>) &#123;</span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/login?redirect=&quot;</span> + to.<span class="property">fullPath</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="title function_">next</span>();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，创建了路由守卫，但是需要判断的是需要对哪个路由进行守卫，这里就是通过元数据来进行判断的。如果所跳转到的路由有元数据，并且对应的<code>auth</code>属性为<code>true</code>表明是需要进行守卫的，那么下面就需要校验用户是否登录,这里是通过判断否<code>window.isLogin</code>的值是否为<code>true</code>来进行判断的（这里简化了操作,实际应用中应该存储到<code>sessionStorage</code>），如果条件成立则表明用户登录，就继续访问用户希望访问到的页面，否则跳转到登录页面，而且将用户希望访问的页面地址也传递到了登录页面，这样用户登录成功后，可以直接跳转到要访问的页面。</p>
<p>如果没有元数据，则继续访问用户要访问的页面。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/login&quot;</span>, <span class="attr">component</span>: <span class="title class_">Login</span> &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">App</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="title class_">Users</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">auth</span>: <span class="literal">true</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/userinfo/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">UserInfo</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/rights&quot;</span>, <span class="attr">component</span>: <span class="title class_">Rights</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/goods&quot;</span>, <span class="attr">component</span>: <span class="title class_">Goods</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/orders&quot;</span>, <span class="attr">component</span>: <span class="title class_">Orders</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/settings&quot;</span>, <span class="attr">component</span>: <span class="title class_">Settings</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，给<code>/users</code>路由添加了元数据。</p>
<p>登录组件创建如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">const Login = &#123; data() &#123; return &#123; isLogin: window.isLogin, &#125;; &#125;, template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">          &lt;button @click=&quot;login&quot; v-if=&quot;!isLogin&quot;&gt;登录&lt;/button&gt;</span><br><span class="line">          &lt;button @click=&quot;logout&quot; v-else&gt;注销&lt;/button&gt;</span><br><span class="line">          &lt;/div&gt;</span><br><span class="line">`, methods: &#123; login() &#123; window.isLogin = true;</span><br><span class="line">this.$router.push(this.$route.query.redirect); &#125;, logout() &#123; this.isLogin =</span><br><span class="line">window.isLogin = false; &#125;, &#125;, &#125;;</span><br></pre></td></tr></table></figure>

<p>当单击登录按钮后，进行将<code>window.isLogin</code>设置为<code>true</code>, 并且进行跳转。</p>
<p>全部代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;title&gt;基于vue-router的案例&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./lib/vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script src=&quot;https://unpkg.com/vue-router/dist/vue-router.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;style type=&quot;text/css&quot;&gt;</span><br><span class="line">      html,</span><br><span class="line">      body,</span><br><span class="line">      #app &#123;</span><br><span class="line">        margin: 0;</span><br><span class="line">        padding: 0px;</span><br><span class="line">        height: 100%;</span><br><span class="line">      &#125;</span><br><span class="line">      .header &#123;</span><br><span class="line">        height: 50px;</span><br><span class="line">        background-color: #545c64;</span><br><span class="line">        line-height: 50px;</span><br><span class="line">        text-align: center;</span><br><span class="line">        font-size: 24px;</span><br><span class="line">        color: #fff;</span><br><span class="line">      &#125;</span><br><span class="line">      .footer &#123;</span><br><span class="line">        height: 40px;</span><br><span class="line">        line-height: 40px;</span><br><span class="line">        background-color: #888;</span><br><span class="line">        position: absolute;</span><br><span class="line">        bottom: 0;</span><br><span class="line">        width: 100%;</span><br><span class="line">        text-align: center;</span><br><span class="line">        color: #fff;</span><br><span class="line">      &#125;</span><br><span class="line">      .main &#123;</span><br><span class="line">        display: flex;</span><br><span class="line">        position: absolute;</span><br><span class="line">        top: 50px;</span><br><span class="line">        bottom: 40px;</span><br><span class="line">        width: 100%;</span><br><span class="line">      &#125;</span><br><span class="line">      .content &#123;</span><br><span class="line">        flex: 1;</span><br><span class="line">        text-align: center;</span><br><span class="line">        height: 100%;</span><br><span class="line">      &#125;</span><br><span class="line">      .left &#123;</span><br><span class="line">        flex: 0 0 20%;</span><br><span class="line">        background-color: #545c64;</span><br><span class="line">      &#125;</span><br><span class="line">      .left a &#123;</span><br><span class="line">        color: white;</span><br><span class="line">        text-decoration: none;</span><br><span class="line">      &#125;</span><br><span class="line">      .right &#123;</span><br><span class="line">        margin: 5px;</span><br><span class="line">      &#125;</span><br><span class="line">      .btns &#123;</span><br><span class="line">        width: 100%;</span><br><span class="line">        height: 35px;</span><br><span class="line">        line-height: 35px;</span><br><span class="line">        background-color: #f5f5f5;</span><br><span class="line">        text-align: left;</span><br><span class="line">        padding-left: 10px;</span><br><span class="line">        box-sizing: border-box;</span><br><span class="line">      &#125;</span><br><span class="line">      button &#123;</span><br><span class="line">        height: 30px;</span><br><span class="line">        background-color: #ecf5ff;</span><br><span class="line">        border: 1px solid lightskyblue;</span><br><span class="line">        font-size: 12px;</span><br><span class="line">        padding: 0 20px;</span><br><span class="line">      &#125;</span><br><span class="line">      .main-content &#123;</span><br><span class="line">        margin-top: 10px;</span><br><span class="line">      &#125;</span><br><span class="line">      ul &#123;</span><br><span class="line">        margin: 0;</span><br><span class="line">        padding: 0;</span><br><span class="line">        list-style: none;</span><br><span class="line">      &#125;</span><br><span class="line">      ul li &#123;</span><br><span class="line">        height: 45px;</span><br><span class="line">        line-height: 45px;</span><br><span class="line">        background-color: #a0a0a0;</span><br><span class="line">        color: #fff;</span><br><span class="line">        cursor: pointer;</span><br><span class="line">        border-bottom: 1px solid #fff;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      table &#123;</span><br><span class="line">        width: 100%;</span><br><span class="line">        border-collapse: collapse;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      td,</span><br><span class="line">      th &#123;</span><br><span class="line">        border: 1px solid #eee;</span><br><span class="line">        line-height: 35px;</span><br><span class="line">        font-size: 12px;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      th &#123;</span><br><span class="line">        background-color: #ddd;</span><br><span class="line">      &#125;</span><br><span class="line">    &lt;/style&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;&lt;router-view&gt;&lt;/router-view&gt;&lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const App = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">      &lt;!-- 头部区域 --&gt;</span><br><span class="line">      &lt;header class=&quot;header&quot;&gt;传智后台管理系统&lt;/header&gt;</span><br><span class="line">      &lt;!-- 中间主体区域 --&gt;</span><br><span class="line">      &lt;div class=&quot;main&quot;&gt;</span><br><span class="line">        &lt;!-- 左侧菜单栏 --&gt;</span><br><span class="line">        &lt;div class=&quot;content left&quot;&gt;</span><br><span class="line">          &lt;ul&gt;</span><br><span class="line">            &lt;li&gt;&lt;router-link to=&quot;/users&quot;&gt; 用户管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">            &lt;li&gt;&lt;router-link to=&quot;/rights&quot;&gt; 权限管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">            &lt;li&gt;&lt;router-link to=&quot;/goods&quot;&gt; 商品管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">            &lt;li&gt;&lt;router-link to=&quot;/orders&quot;&gt; 订单管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">            &lt;li&gt;&lt;router-link to=&quot;/settings&quot;&gt; 系统设置&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">          &lt;/ul&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &lt;!-- 右侧内容区域 --&gt;</span><br><span class="line">        &lt;div class=&quot;content right&quot;&gt;&lt;div class=&quot;main-content&quot;&gt; &lt;router-view /&gt;&lt;/div&gt;&lt;/div&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">      &lt;!-- 尾部区域 --&gt;</span><br><span class="line">      &lt;footer class=&quot;footer&quot;&gt;版权信息&lt;/footer&gt;</span><br><span class="line">    &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      const Users = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            userlist: [</span><br><span class="line">              &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span><br><span class="line">              &#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;,</span><br><span class="line">              &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;,</span><br><span class="line">              &#123; id: 4, name: &quot;赵六&quot;, age: 40 &#125;,</span><br><span class="line">            ],</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          goDetail(id) &#123;</span><br><span class="line">            console.log(id);</span><br><span class="line">            this.$router.push(&quot;/userinfo/&quot; + id);</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;用户管理区域&lt;/h3&gt;</span><br><span class="line">        &lt;table&gt;</span><br><span class="line">          &lt;thead&gt;</span><br><span class="line">            &lt;tr&gt;&lt;th&gt;编号&lt;/th&gt;&lt;th&gt;姓名&lt;/th&gt;&lt;th&gt;年龄&lt;/th&gt;&lt;th&gt;操作&lt;/th&gt;&lt;/tr&gt;</span><br><span class="line">          &lt;/thead&gt;</span><br><span class="line">          &lt;tbody&gt;</span><br><span class="line">            &lt;tr v-for=&quot;item in userlist&quot; :key=&quot;item.id&quot;&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.id&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.name&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;&#123;&#123;item.age&#125;&#125;&lt;/td&gt;</span><br><span class="line">              &lt;td&gt;</span><br><span class="line">                &lt;a href=&quot;javascript:;&quot; @click=&quot;goDetail(item.id)&quot;&gt;详情&lt;/a&gt;</span><br><span class="line">              &lt;/td&gt;</span><br><span class="line">            &lt;/tr&gt;</span><br><span class="line">          &lt;/tbody&gt;</span><br><span class="line">        &lt;/table&gt;</span><br><span class="line">      &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      //用户详情组件</span><br><span class="line">      const UserInfo = &#123;</span><br><span class="line">        props: [&quot;id&quot;],</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">          &lt;h5&gt;用户详情页 --- 用户Id为：&#123;&#123;id&#125;&#125;&lt;/h5&gt;</span><br><span class="line">          &lt;button @click=&quot;goback()&quot;&gt;后退&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;`,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          goback() &#123;</span><br><span class="line">            // 实现后退功能</span><br><span class="line">            this.$router.go(-1);</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;;</span><br><span class="line"></span><br><span class="line">      const Rights = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;权限管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      const Goods = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;商品管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      const Orders = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;订单管理区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      const Settings = &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">        &lt;h3&gt;系统设置区域&lt;/h3&gt;</span><br><span class="line">      &lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      const Login = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            isLogin: window.isLogin,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">          &lt;button @click=&quot;login&quot; v-if=&quot;!isLogin&quot;&gt;登录&lt;/button&gt;</span><br><span class="line">          &lt;button @click=&quot;logout&quot; v-else&gt;注销&lt;/button&gt;</span><br><span class="line">          &lt;/div&gt;`,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          login() &#123;</span><br><span class="line">            window.isLogin = true;</span><br><span class="line">            this.$router.push(this.$route.query.redirect);</span><br><span class="line">          &#125;,</span><br><span class="line">          logout() &#123;</span><br><span class="line">            this.isLogin = window.isLogin = false;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;;</span><br><span class="line"></span><br><span class="line">      // 创建路由对象</span><br><span class="line">      const router = new VueRouter(&#123;</span><br><span class="line">        routes: [</span><br><span class="line">          &#123; path: &quot;/login&quot;, component: Login &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            path: &quot;/&quot;,</span><br><span class="line">            component: App,</span><br><span class="line">            redirect: &quot;/users&quot;,</span><br><span class="line">            children: [</span><br><span class="line">              &#123;</span><br><span class="line">                path: &quot;/users&quot;,</span><br><span class="line">                component: Users,</span><br><span class="line">                meta: &#123;</span><br><span class="line">                  auth: true,</span><br><span class="line">                &#125;,</span><br><span class="line">              &#125;,</span><br><span class="line">              &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span><br><span class="line">              &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span><br><span class="line">              &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span><br><span class="line">              &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span><br><span class="line">              &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span><br><span class="line">            ],</span><br><span class="line">          &#125;,</span><br><span class="line">        ],</span><br><span class="line">      &#125;);</span><br><span class="line">      //实现全局守卫</span><br><span class="line">      router.beforeEach((to, from, next) =&gt; &#123;</span><br><span class="line">        //to:去哪个页面，from来自哪个页面，next继续执行.</span><br><span class="line">        //判断哪个路由需要进行守卫，这里可以通过元数据方式</span><br><span class="line">        if (to.meta.auth) &#123;</span><br><span class="line">          if (window.isLogin) &#123;</span><br><span class="line">            next();</span><br><span class="line">          &#125; else &#123;</span><br><span class="line">            next(&quot;/login?redirect=&quot; + to.fullPath);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">          next();</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;);</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        router,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>以上是全局守卫，对所有的路由都起作用。</p>
<p>但是，如果项目比较简单，路由规则定义的比较少，可以将守卫定位到某个路由规则内。这就是<strong>路由独享守卫</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/login&quot;</span>, <span class="attr">component</span>: <span class="title class_">Login</span> &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">App</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">      <span class="attr">children</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">          <span class="attr">component</span>: <span class="title class_">Users</span>,</span><br><span class="line">          <span class="attr">meta</span>: &#123;</span><br><span class="line">            <span class="attr">auth</span>: <span class="literal">true</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="title function_">beforeEnter</span>(<span class="params">to, <span class="keyword">from</span>, next</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">isLogin</span>) &#123;</span><br><span class="line">              <span class="title function_">next</span>();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">              <span class="title function_">next</span>(<span class="string">&quot;/login?redirect=&quot;</span> + to.<span class="property">fullPath</span>);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/userinfo/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">UserInfo</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/rights&quot;</span>, <span class="attr">component</span>: <span class="title class_">Rights</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/goods&quot;</span>, <span class="attr">component</span>: <span class="title class_">Goods</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/orders&quot;</span>, <span class="attr">component</span>: <span class="title class_">Orders</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/settings&quot;</span>, <span class="attr">component</span>: <span class="title class_">Settings</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，给<code>/users</code>这个路由守卫，注意这里的方法名为<code>beforeEnter</code>.同时，这里将守卫定义在<code>/users</code>路由规则内，所以不需要对元数据进行判断，只需要判断用户是否登录就可以了。（注意：在进行以上测试时，需要将全局守卫的代码注释掉）</p>
<p><strong>组件内守卫</strong></p>
<p>可以在路由组件内直接定义以下路由导航守卫。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">beforeRouteEnter</span><br><span class="line">beforeRouteUpdate</span><br><span class="line">beforeRouteLeave</span><br></pre></td></tr></table></figure>

<p>将如下的代码直接添加到组件内。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Users</span> = &#123;</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">userlist</span>: [</span><br><span class="line">        &#123; <span class="attr">id</span>: <span class="number">1</span>, <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>, <span class="attr">age</span>: <span class="number">10</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">id</span>: <span class="number">2</span>, <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>, <span class="attr">age</span>: <span class="number">20</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">id</span>: <span class="number">3</span>, <span class="attr">name</span>: <span class="string">&quot;王五&quot;</span>, <span class="attr">age</span>: <span class="number">30</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">id</span>: <span class="number">4</span>, <span class="attr">name</span>: <span class="string">&quot;赵六&quot;</span>, <span class="attr">age</span>: <span class="number">40</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">goDetail</span>(<span class="params">id</span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(id);</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="string">&quot;/userinfo/&quot;</span> + id);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;</span></span><br><span class="line"><span class="string">          &lt;h3&gt;用户管理区域&lt;/h3&gt;</span></span><br><span class="line"><span class="string">          &lt;table&gt;</span></span><br><span class="line"><span class="string">            &lt;thead&gt;</span></span><br><span class="line"><span class="string">              &lt;tr&gt;&lt;th&gt;编号&lt;/th&gt;&lt;th&gt;姓名&lt;/th&gt;&lt;th&gt;年龄&lt;/th&gt;&lt;th&gt;操作&lt;/th&gt;&lt;/tr&gt;</span></span><br><span class="line"><span class="string">            &lt;/thead&gt;</span></span><br><span class="line"><span class="string">            &lt;tbody&gt;</span></span><br><span class="line"><span class="string">              &lt;tr v-for=&quot;item in userlist&quot; :key=&quot;item.id&quot;&gt;</span></span><br><span class="line"><span class="string">                &lt;td&gt;&#123;&#123;item.id&#125;&#125;&lt;/td&gt;</span></span><br><span class="line"><span class="string">                &lt;td&gt;&#123;&#123;item.name&#125;&#125;&lt;/td&gt;</span></span><br><span class="line"><span class="string">                &lt;td&gt;&#123;&#123;item.age&#125;&#125;&lt;/td&gt;</span></span><br><span class="line"><span class="string">                &lt;td&gt;</span></span><br><span class="line"><span class="string">                  &lt;a href=&quot;javascript:;&quot; @click=&quot;goDetail(item.id)&quot;&gt;详情&lt;/a&gt;</span></span><br><span class="line"><span class="string">                &lt;/td&gt;</span></span><br><span class="line"><span class="string">              &lt;/tr&gt;</span></span><br><span class="line"><span class="string">            &lt;/tbody&gt;</span></span><br><span class="line"><span class="string">          &lt;/table&gt;</span></span><br><span class="line"><span class="string">        &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="title function_">beforeRouteEnter</span>(<span class="params">to, <span class="keyword">from</span>, next</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">isLogin</span>) &#123;</span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/login?redirect=&quot;</span> + to.<span class="property">fullPath</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，直接将路由守卫对应的方法添加到了组件中。</p>
<p>注意：在测试之前将路由规则中定义的路由守卫的代码注释掉。</p>
<h2 id="11、addRoutes-动态路由添加"><a href="#11、addRoutes-动态路由添加" class="headerlink" title="11、addRoutes 动态路由添加"></a>11、addRoutes 动态路由添加</h2><p>在前面的案例中，我们都是将路由定义好，然后通过路由守卫来判断，某个用户是否登录，从而决定能否访问某个路由规则对应的组件内容。</p>
<p>但是，如果某些路由规则只能用户登录以后才能够访问，那么我们也可以不用提前定义好，而是在登录后，通过<code>addRoutes</code>方法为其动态的添加。</p>
<p>首先这里需要，还需要全局的路由守卫来进行校验判断，只不过这里全局路由守卫的逻辑发生了变化。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">router.<span class="title function_">beforeEach</span>(<span class="function">(<span class="params">to, <span class="keyword">from</span>, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">//to:去哪个页面，from来自哪个页面，next继续执行.</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">isLogin</span>) &#123;</span><br><span class="line">    <span class="comment">//用户已经登录</span></span><br><span class="line">    <span class="keyword">if</span> (to.<span class="property">path</span> === <span class="string">&quot;/login&quot;</span>) &#123;</span><br><span class="line">      <span class="comment">// 用户已经登录了，但是又访问登录页面，这里直接跳转到用户列表页面</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//用户已经登录，并且访问其它页面，则运行访问</span></span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">//用户没有登录,并且访问的就是登录页，则运行访问登录页</span></span><br><span class="line">    <span class="keyword">if</span> (to.<span class="property">path</span> === <span class="string">&quot;/login&quot;</span>) &#123;</span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//用户没有登录，访问其它页面，则跳转到登录页面。</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/login?redirect=&quot;</span> + to.<span class="property">fullPath</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>下面对登录组件进行修改</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">const Login = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            isLogin: window.isLogin,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">            &lt;button @click=&quot;login&quot; v-if=&quot;!isLogin&quot;&gt;登录&lt;/button&gt;</span><br><span class="line">            &lt;button @click=&quot;logout&quot; v-else&gt;注销&lt;/button&gt;</span><br><span class="line">            &lt;/div&gt;`,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          login() &#123;</span><br><span class="line">            window.isLogin = true;</span><br><span class="line">            if (this.$route.query.redirect) &#123;</span><br><span class="line">              //动态添加路由：</span><br><span class="line">              this.$router.addRoutes([</span><br><span class="line">                &#123;</span><br><span class="line">                  path: &quot;/&quot;,</span><br><span class="line">                  component: App,</span><br><span class="line">                  redirect: &quot;/users&quot;,</span><br><span class="line">                  children: [</span><br><span class="line">                    &#123;</span><br><span class="line">                      path: &quot;/users&quot;,</span><br><span class="line">                      component: Users,</span><br><span class="line">                      meta: &#123;</span><br><span class="line">                        auth: true,</span><br><span class="line">                      &#125;,</span><br><span class="line">                      // beforeEnter(to, from, next) &#123;</span><br><span class="line">                      //   if (window.isLogin) &#123;</span><br><span class="line">                      //     next();</span><br><span class="line">                      //   &#125; else &#123;</span><br><span class="line">                      //     next(&quot;/login?redirect=&quot; + to.fullPath);</span><br><span class="line">                      //   &#125;</span><br><span class="line">                      // &#125;,</span><br><span class="line">                    &#125;,</span><br><span class="line">                    &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span><br><span class="line">                    &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span><br><span class="line">                    &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span><br><span class="line">                    &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span><br><span class="line">                    &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span><br><span class="line">                  ],</span><br><span class="line">                &#125;,</span><br><span class="line">              ]);</span><br><span class="line">              this.$router.push(this.$route.query.redirect);</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">              this.$router.push(&quot;/&quot;);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;,</span><br><span class="line">          logout() &#123;</span><br><span class="line">            this.isLogin = window.isLogin = false;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;;</span><br></pre></td></tr></table></figure>

<p>在登录成功后，通过<code>addRoutes</code>方法动态的添加路由规则，也就是所添加的路由规则只能是在登录以后才能够访问，所以全局守卫的判断条件发生了变化，不在判断是否有元数据，而只是判断是否登录。如果登录了，想访问上面的路由规则，则运行访问，如果没有登录则不允许访问。</p>
<p>注意：对应的原有的路由规则应该注释掉。</p>
<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>基于vue-router的案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue-router/dist/vue-router.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">html</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">body</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-id">#app</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.header</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">24px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.footer</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#888</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">display</span>: flex;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">50px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">bottom</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">1</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#545c64</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.left</span> <span class="selector-tag">a</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: white;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-decoration</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.right</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">5px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.btns</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">text-align</span>: left;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding-left</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">box-sizing</span>: border-box;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">button</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">30px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ecf5ff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid lightskyblue;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.main-content</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin-top</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">margin</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">list-style</span>: none;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">ul</span> <span class="selector-tag">li</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">45px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#a0a0a0</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">cursor</span>: pointer;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-bottom</span>: <span class="number">1px</span> solid <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">table</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-collapse</span>: collapse;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">td</span>,</span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#eee</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">line-height</span>: <span class="number">35px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">12px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">th</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#ddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const App = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 头部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">header</span> <span class="attr">class</span>=<span class="string">&quot;header&quot;</span>&gt;</span>传智后台管理系统<span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 中间主体区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 左侧菜单栏 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content left&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/users&quot;</span>&gt;</span> 用户管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/rights&quot;</span>&gt;</span> 权限管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/goods&quot;</span>&gt;</span> 商品管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/orders&quot;</span>&gt;</span> 订单管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/settings&quot;</span>&gt;</span> 系统设置<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 右侧内容区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content right&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main-content&quot;</span>&gt;</span> <span class="tag">&lt;<span class="name">router-view</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 尾部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">footer</span> <span class="attr">class</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>版权信息<span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Users = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          return &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            userlist: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 4, name: &quot;赵六&quot;, age: 40 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goDetail(id) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            console.log(id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.push(&quot;/userinfo/&quot; + id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>用户管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">tr</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>编号<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>姓名<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>年龄<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>操作<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">tr</span> <span class="attr">v-for</span>=<span class="string">&quot;item in userlist&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.name</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.age</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;goDetail(item.id)&quot;</span>&gt;</span>详情<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // beforeRouteEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //用户详情组件</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const UserInfo = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;id&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">h5</span>&gt;</span>用户详情页 --- 用户Id为：</span><span class="template-variable">&#123;&#123;<span class="name">id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;goback()&quot;</span>&gt;</span>后退<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goback() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // 实现后退功能</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.go(-1);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Rights = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>权限管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Goods = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>商品管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Orders = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>订单管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Settings = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>系统设置区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Login = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          return &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            isLogin: window.isLogin,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;login&quot;</span> <span class="attr">v-if</span>=<span class="string">&quot;!isLogin&quot;</span>&gt;</span>登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;logout&quot;</span> <span class="attr">v-else</span>&gt;</span>注销<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          login() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            window.isLogin = true;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            if (this.$route.query.redirect) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //动态添加路由：</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              this.$router.addRoutes([</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  path: &quot;/&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  component: App,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  redirect: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      path: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      component: Users,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      meta: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        auth: true,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      // beforeEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                      // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              ]);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              this.$router.push(this.$route.query.redirect);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              this.$router.push(&quot;/&quot;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          logout() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.isLogin = window.isLogin = false;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // 创建路由对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const router = new VueRouter(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        routes: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123; path: &quot;/login&quot;, component: Login &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          // &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //   path: &quot;/&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //   component: App,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //   redirect: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //   children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       path: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       component: Users,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       meta: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //         auth: true,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       // beforeEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //       // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //     &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //   ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //实现全局守卫</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // router.beforeEach((to, from, next) =&gt; &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   //to:去哪个页面，from来自哪个页面，next继续执行.</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   //判断哪个路由需要进行守卫，这里可以通过元数据方式</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   if (to.meta.auth) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //       next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //       next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      router.beforeEach((to, from, next) =&gt; &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //to:去哪个页面，from来自哪个页面，next继续执行.</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //用户已经登录</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          if (to.path === &quot;/login&quot;) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // 用户已经登录了，但是又访问登录页面，这里直接跳转到用户列表页面</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next(&quot;/&quot;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            //用户已经登录，并且访问其它页面，则运行访问</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //用户没有登录,并且访问的就是登录页，则运行访问登录页</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          if (to.path === &quot;/login&quot;) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            //用户没有登录，访问其它页面，则跳转到登录页面。</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        router,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="12、路由组件缓存"><a href="#12、路由组件缓存" class="headerlink" title="12、路由组件缓存"></a>12、路由组件缓存</h2><p>利用<code>keepalive</code>做组件缓存，保留组件状态，提高执行效率。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;keep-alive include=&quot;home&quot;&gt;</span><br><span class="line">    &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">&lt;/keep-alive&gt;</span><br></pre></td></tr></table></figure>

<p>使用<code>include</code>或者<code>exclude</code>时要给组件设置<code>name</code>（这个是组件的名称，组件的名称通过给组件添加<code>name</code>属性来进行设置）</p>
<p>当我们进行路由切换的时候，对应的组件会被重新创建，同时数据也会不断的重新加载。</p>
<p>如果数据没有变化，就没有必要每次都重新发送异步请求加载数据</p>
<p>现在，在<code>App</code>组件中添加<code>keep-alive</code></p>
<p>因为切换的组件都是在该<code>router-view</code>中进行展示。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 右侧内容区域 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content right&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main-content&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">keep-alive</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">router-view</span> /&gt;</span></span><br><span class="line">           <span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面可以进行验证。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Rights</span> = &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;</span></span><br><span class="line"><span class="string">          &lt;h3&gt;权限管理区域&lt;/h3&gt;</span></span><br><span class="line"><span class="string">        &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="title function_">created</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在<code>Rights</code>组件中，添加了<code>created</code>方法，该方法中输出日期时间，但是我们不断的切换，发现并不是每次都打印日期时间内容。</p>
<p>当然，以上<code>keep-alive</code>的使用方式，是将所有的组件都缓存了，如果只想缓存某个组件，可以采用如下的方式</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!-- 右侧内容区域 --&gt;</span><br><span class="line">         &lt;div class=&quot;content right&quot;&gt;&lt;div class=&quot;main-content&quot;&gt;</span><br><span class="line">           &lt;keep-alive include=&#x27;goods&#x27;&gt;</span><br><span class="line">            &lt;router-view /&gt;</span><br><span class="line">            &lt;/keep-alive&gt;</span><br><span class="line">            &lt;/div&gt;&lt;/div&gt;</span><br><span class="line">       &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，通过<code>include</code>添加了需要缓存的组件的名称，如果有多个在<code>include</code>中可以继续添加，每个组件名称之间用逗号分隔。</p>
<p>以上的含义就是只有<code>goods</code>组件需要被缓存(<code>goods</code>是组件的<code>name</code>值)</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Goods</span> = &#123;</span><br><span class="line">  <span class="attr">name</span>: <span class="string">&quot;goods&quot;</span>,</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;</span></span><br><span class="line"><span class="string">          &lt;h3&gt;商品管理区域&lt;/h3&gt;</span></span><br><span class="line"><span class="string">        &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="title function_">created</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p><code>exclude</code>表示的就是除了指定的组件以外（也是组件的<code>name</code>），其它组件都进行缓存。</p>
<p><strong>应用场景</strong></p>
<p>如果未使用 keep-alive 组件，则在页面回退时仍然会重新渲染页面，触发 created 钩子，使用体验不好。 在以下场景中使用 keep-alive 组件会显著提高用户体验，菜单存在多级关系，多见于列表页+详情页的场景如：</p>
<ul>
<li>商品列表页点击商品跳转到商品详情，返回后仍显示原有信息</li>
<li>订单列表跳转到订单详情，返回，等等场景。</li>
</ul>
<p><strong>生命周期：</strong><br> <code>activated</code>和<code>deactivated</code>会在<code>keep-alive</code>内所有嵌套的组件中触发<br>  如：B 页面是缓存页面<br>    当 A 页面跳到 B 页面时，B 页面的生命周期：activated（可在此时更新数据）<br>   B 页面跳出时，触发 deactivated<br>   B 页面自身刷新时，会触发 created-mouted-activated</p>
<h2 id="13、Hash-模式与-History-模式"><a href="#13、Hash-模式与-History-模式" class="headerlink" title="13、Hash 模式与 History 模式"></a>13、Hash 模式与 History 模式</h2><h3 id="13-1-Hash-模式与-History-模式区别"><a href="#13-1-Hash-模式与-History-模式区别" class="headerlink" title="13.1 Hash 模式与 History 模式区别"></a>13.1 Hash 模式与 History 模式区别</h3><p>前端路由中，不管是什么实现模式，都是客户端的一种实现方式，也就是当路径发生变化的时候，是不会向服务器发送请求的。</p>
<p>如果需要向服务器发送请求，需要用到<code>ajax</code>方式。</p>
<p>两种模式的区别</p>
<p>首先是表现形式的区别</p>
<p><strong><code>Hash</code>模式</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">https://www.baidu.com/#/showlist?id=22256</span><br></pre></td></tr></table></figure>

<p><code>hash</code>模式中路径带有<code>#</code>, <code>#</code>后面的内容作为路由地址。可以通过问号携带参数。</p>
<p>当然这种模式相对来说比较丑，路径中带有与数据无关的符号，例如<code>#</code>与<code>?</code></p>
<p><code>History</code>模式</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">https://www.baidu.com/showlist/22256</span><br></pre></td></tr></table></figure>

<p><code>History</code>模式是一个正常的路径的模式，如果要想实现这种模式，还需要服务端的相应支持。</p>
<p>下面再来看一下两者原理上的区别。</p>
<p><code>Hash</code>模式是基于锚点，以及<code>onhashchange</code>事件。</p>
<p>通过锚点的值作为路由地址，当地址发生变化后触发<code>onhashchange</code>事件。</p>
<p><code>History</code>模式是基于<code>HTML5</code>中的<code>History API</code></p>
<p>也就是如下两个方法</p>
<p><code>history.pushState( )</code> <code>IE10</code>以后才支持</p>
<p><code>history.replaceState( )</code></p>
<h3 id="13-2-History模式的使用"><a href="#13-2-History模式的使用" class="headerlink" title="13.2 History模式的使用"></a>13.2 <code>History</code>模式的使用</h3><p><code>History</code>模式需要服务器的支持，为什么呢？</p>
<p>因为在单页面的应用中，只有一个页面，也就是<code>index.html</code>这个页面，服务端不存在<code>http://www.test.com/login</code>这样的地址，也就说如果刷新浏览器，</p>
<p>请求服务器，是找不到<code>/login</code>这个页面的，所以会出现<code>404</code>的错误。（在传统的开发模式下，输入以上的地址，会返回<code>login</code>这个页面，而在单页面应用中，只有一个页面为<code>index.html</code>）</p>
<p>所以说，在服务端应该除了静态资源外都返回单页应用的<code>index.html</code></p>
<p>下面我们开始<code>history</code>模式来演示一下对应的问题。</p>
<p>首先添加一个针对 404 组件的处理</p>
<p>首先在菜单栏中添加一个链接：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!-- 左侧菜单栏 --&gt;</span><br><span class="line">&lt;div class=&quot;content left&quot;&gt;</span><br><span class="line">            &lt;ul&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/users&quot;&gt; 用户管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/rights&quot;&gt; 权限管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/goods&quot;&gt; 商品管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/orders&quot;&gt; 订单管理&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/settings&quot;&gt; 系统设置&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">              &lt;li&gt;&lt;router-link to=&quot;/about&quot;&gt; 关于&lt;/router-link&gt;&lt;/li&gt;</span><br><span class="line">            &lt;/ul&gt;</span><br><span class="line">          &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>这里我们添加了一个“关于”的链接，但是我们没有为其定义相应的组件，所以这里需要处理 404 的情况。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">const NotFound = &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">            你访问的页面不存在!!</span><br><span class="line">          &lt;/div&gt;</span><br><span class="line">`, &#125;;</span><br></pre></td></tr></table></figure>

<p>在程序中添加了一个针对 404 的组件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">       <span class="attr">mode</span>: <span class="string">&quot;history&quot;</span>,</span><br><span class="line">       <span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">       <span class="attr">mode</span>: <span class="string">&quot;history&quot;</span>,</span><br><span class="line">       <span class="attr">routes</span>: [</span><br><span class="line">         &#123; <span class="attr">path</span>: <span class="string">&quot;/login&quot;</span>, <span class="attr">component</span>: <span class="title class_">Login</span> &#125;,</span><br><span class="line">         &#123; <span class="attr">path</span>: <span class="string">&quot;*&quot;</span>, <span class="attr">component</span>: <span class="title class_">NotFound</span> &#125;,</span><br><span class="line">         &#123;</span><br><span class="line">           <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">           <span class="attr">component</span>: <span class="title class_">App</span>,</span><br><span class="line">           <span class="attr">redirect</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">           <span class="attr">children</span>: [</span><br><span class="line">             &#123;</span><br><span class="line">               <span class="attr">path</span>: <span class="string">&quot;/users&quot;</span>,</span><br><span class="line">               <span class="attr">component</span>: <span class="title class_">Users</span>,</span><br><span class="line">               <span class="attr">meta</span>: &#123;</span><br><span class="line">                 <span class="attr">auth</span>: <span class="literal">true</span>,</span><br><span class="line">               &#125;,</span><br><span class="line">               <span class="comment">// beforeEnter(to, from, next) &#123;</span></span><br><span class="line">               <span class="comment">//   if (window.isLogin) &#123;</span></span><br><span class="line">               <span class="comment">//     next();</span></span><br><span class="line">               <span class="comment">//   &#125; else &#123;</span></span><br><span class="line">               <span class="comment">//     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span><br><span class="line">               <span class="comment">//   &#125;</span></span><br><span class="line">               <span class="comment">// &#125;,</span></span><br><span class="line">             &#125;,</span><br><span class="line">             &#123; <span class="attr">path</span>: <span class="string">&quot;/userinfo/:id&quot;</span>, <span class="attr">component</span>: <span class="title class_">UserInfo</span>, <span class="attr">props</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">             &#123; <span class="attr">path</span>: <span class="string">&quot;/rights&quot;</span>, <span class="attr">component</span>: <span class="title class_">Rights</span> &#125;,</span><br><span class="line">             &#123; <span class="attr">path</span>: <span class="string">&quot;/goods&quot;</span>, <span class="attr">component</span>: <span class="title class_">Goods</span> &#125;,</span><br><span class="line">             &#123; <span class="attr">path</span>: <span class="string">&quot;/orders&quot;</span>, <span class="attr">component</span>: <span class="title class_">Orders</span> &#125;,</span><br><span class="line">             &#123; <span class="attr">path</span>: <span class="string">&quot;/settings&quot;</span>, <span class="attr">component</span>: <span class="title class_">Settings</span> &#125;,</span><br><span class="line">           ],</span><br><span class="line">         &#125;,</span><br><span class="line">       ],</span><br><span class="line">     &#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，指定了处理 404 的路由规则，同时将路由的模式修改成了<code>history</code>模式。同时，启用这里启用了其它的组件的路由规则配置，也就是不在<code>login</code>方法中使用<code>addRoutes</code>方法来动态添加路由规则了。</p>
<p><code>login</code> 方法修改成如下形式：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">login</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="comment">// window.isLogin = true;</span></span><br><span class="line">           <span class="variable language_">window</span>.<span class="property">sessionStorage</span>.<span class="title function_">setItem</span>(<span class="string">&quot;isLogin&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">           <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$route</span>.<span class="property">query</span>.<span class="property">redirect</span>) &#123;</span><br><span class="line">             <span class="comment">//   //动态添加路由：</span></span><br><span class="line">             <span class="comment">//   this.$router.addRoutes([</span></span><br><span class="line">             <span class="comment">//     &#123;</span></span><br><span class="line">             <span class="comment">//       path: &quot;/&quot;,</span></span><br><span class="line">             <span class="comment">//       component: App,</span></span><br><span class="line">             <span class="comment">//       redirect: &quot;/users&quot;,</span></span><br><span class="line">             <span class="comment">//       children: [</span></span><br><span class="line">             <span class="comment">//         &#123;</span></span><br><span class="line">             <span class="comment">//           path: &quot;/users&quot;,</span></span><br><span class="line">             <span class="comment">//           component: Users,</span></span><br><span class="line">             <span class="comment">//           meta: &#123;</span></span><br><span class="line">             <span class="comment">//             auth: true,</span></span><br><span class="line">             <span class="comment">//           &#125;,</span></span><br><span class="line">             <span class="comment">//           // beforeEnter(to, from, next) &#123;</span></span><br><span class="line">             <span class="comment">//           //   if (window.isLogin) &#123;</span></span><br><span class="line">             <span class="comment">//           //     next();</span></span><br><span class="line">             <span class="comment">//           //   &#125; else &#123;</span></span><br><span class="line">             <span class="comment">//           //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span><br><span class="line">             <span class="comment">//           //   &#125;</span></span><br><span class="line">             <span class="comment">//           // &#125;,</span></span><br><span class="line">             <span class="comment">//         &#125;,</span></span><br><span class="line">             <span class="comment">//         &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span><br><span class="line">             <span class="comment">//         &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span><br><span class="line">             <span class="comment">//         &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span><br><span class="line">             <span class="comment">//         &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span><br><span class="line">             <span class="comment">//         &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span><br><span class="line">             <span class="comment">//       ],</span></span><br><span class="line">             <span class="comment">//     &#125;,</span></span><br><span class="line">             <span class="comment">//   ]);</span></span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="variable language_">this</span>.<span class="property">$route</span>.<span class="property">query</span>.<span class="property">redirect</span>);</span><br><span class="line">           &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="string">&quot;/&quot;</span>);</span><br><span class="line">           &#125;</span><br><span class="line">         &#125;</span><br></pre></td></tr></table></figure>

<p>现在已经将前端<code>vue</code>中的代码修改完毕了，下面我们要将页面的内容部署到<code>node.js</code>服务器中。</p>
<p>而且上面的代码中，我们使用了<code>sessionStorage</code>来保存登录用户的信息，不在使用<code>window</code>下的<code>isLogin</code></p>
<p>对应的<code>data</code>内容下的代码也要修改：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Login</span> = &#123;</span><br><span class="line">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="attr">isLogin</span>: <span class="variable language_">window</span>.<span class="property">sessionStorage</span>.<span class="title function_">getItem</span>(<span class="string">&quot;isLogin&quot;</span>),</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>路由守卫中的代码进行如下修改：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">jsrouter.<span class="title function_">beforeEach</span>(<span class="function">(<span class="params">to, <span class="keyword">from</span>, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">//to:去哪个页面，from来自哪个页面，next继续执行.</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">sessionStorage</span>.<span class="title function_">getItem</span>(<span class="string">&quot;isLogin&quot;</span>)) &#123;</span><br><span class="line">    <span class="comment">//用户已经登录</span></span><br><span class="line">    <span class="keyword">if</span> (to.<span class="property">path</span> === <span class="string">&quot;/login&quot;</span>) &#123;</span><br><span class="line">      <span class="comment">// 用户已经登录了，但是又访问登录页面，这里直接跳转到用户列表页面</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//用户已经登录，并且访问其它页面，则运行访问</span></span><br><span class="line"></span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">//用户没有登录,并且访问的就是登录页，则运行访问登录页</span></span><br><span class="line">    <span class="keyword">if</span> (to.<span class="property">path</span> === <span class="string">&quot;/login&quot;</span>) &#123;</span><br><span class="line">      <span class="title function_">next</span>();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//用户没有登录，访问其它页面，则跳转到登录页面。</span></span><br><span class="line">      <span class="title function_">next</span>(<span class="string">&quot;/login?redirect=&quot;</span> + to.<span class="property">fullPath</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们也是通过<code>sessionStorage</code>来获取登录信息。</p>
<p><code>index.html</code>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>基于vue-router的案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./lib/vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue-router/dist/vue-router.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const App = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 头部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">header</span> <span class="attr">class</span>=<span class="string">&quot;header&quot;</span>&gt;</span>传智后台管理系统<span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 中间主体区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 左侧菜单栏 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content left&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/users&quot;</span>&gt;</span> 用户管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/rights&quot;</span>&gt;</span> 权限管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/goods&quot;</span>&gt;</span> 商品管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/orders&quot;</span>&gt;</span> 订单管理<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/settings&quot;</span>&gt;</span> 系统设置<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/about&quot;</span>&gt;</span> 关于<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="comment">&lt;!-- 右侧内容区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;content right&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">keep-alive</span> <span class="attr">include</span>=<span class="string">&#x27;goods&#x27;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">             <span class="tag">&lt;<span class="name">router-view</span> /&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">             <span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">             <span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="comment">&lt;!-- 尾部区域 --&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;<span class="name">footer</span> <span class="attr">class</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>版权信息<span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Users = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          return &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            userlist: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 1, name: &quot;张三&quot;, age: 10 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 2, name: &quot;李四&quot;, age: 20 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 3, name: &quot;王五&quot;, age: 30 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; id: 4, name: &quot;赵六&quot;, age: 40 &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goDetail(id) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            console.log(id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.push(&quot;/userinfo/&quot; + id);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>用户管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">tr</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>编号<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>姓名<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>年龄<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;<span class="name">th</span>&gt;</span>操作<span class="tag">&lt;/<span class="name">th</span>&gt;</span><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">thead</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;<span class="name">tr</span> <span class="attr">v-for</span>=<span class="string">&quot;item in userlist&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.name</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.age</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:;&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;goDetail(item.id)&quot;</span>&gt;</span>详情<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">tbody</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">table</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // beforeRouteEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //用户详情组件</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const UserInfo = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;id&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">h5</span>&gt;</span>用户详情页 --- 用户Id为：</span><span class="template-variable">&#123;&#123;<span class="name">id</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;goback()&quot;</span>&gt;</span>后退<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          goback() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // 实现后退功能</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.$router.go(-1);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Rights = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>权限管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Goods = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        name: &quot;goods&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>商品管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        created() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          console.log(new Date());</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Orders = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>订单管理区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Settings = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;<span class="name">h3</span>&gt;</span>系统设置区域<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const NotFound = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            你访问的页面不存在!!</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const Login = &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          return &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            isLogin: window.sessionStorage.getItem(&quot;isLogin&quot;),</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;login&quot;</span> <span class="attr">v-if</span>=<span class="string">&quot;!isLogin&quot;</span>&gt;</span>登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;logout&quot;</span> <span class="attr">v-else</span>&gt;</span>注销<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        methods: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          login() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // window.isLogin = true;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            window.sessionStorage.setItem(&quot;isLogin&quot;, true);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            if (this.$route.query.redirect) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //   //动态添加路由：</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //   this.$router.addRoutes([</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //     &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //       path: &quot;/&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //       component: App,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //       redirect: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //       children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           path: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           component: Users,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           meta: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //             auth: true,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           // beforeEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //           // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //         &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //       ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //     &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              //   ]);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              this.$router.push(this.$route.query.redirect);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              this.$router.push(&quot;/&quot;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          logout() &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            this.isLogin = window.isLogin = false;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // 创建路由对象</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const router = new VueRouter(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        mode: &quot;history&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        routes: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123; path: &quot;/login&quot;, component: Login &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123; path: &quot;*&quot;, component: NotFound &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            path: &quot;/&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            component: App,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            redirect: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            children: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                path: &quot;/users&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                component: Users,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                meta: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                  auth: true,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                // beforeEnter(to, from, next) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                //   if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                //     next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                // &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/userinfo/:id&quot;, component: UserInfo, props: true &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/rights&quot;, component: Rights &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/goods&quot;, component: Goods &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/orders&quot;, component: Orders &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              &#123; path: &quot;/settings&quot;, component: Settings &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //实现全局守卫</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // router.beforeEach((to, from, next) =&gt; &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   //to:去哪个页面，from来自哪个页面，next继续执行.</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   //判断哪个路由需要进行守卫，这里可以通过元数据方式</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   if (to.meta.auth) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     if (window.isLogin) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //       next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //       next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //     next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      //   &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      // &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      router.beforeEach((to, from, next) =&gt; &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        //to:去哪个页面，from来自哪个页面，next继续执行.</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        if (window.sessionStorage.getItem(&quot;isLogin&quot;)) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //用户已经登录</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          if (to.path === &quot;/login&quot;) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            // 用户已经登录了，但是又访问登录页面，这里直接跳转到用户列表页面</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next(&quot;/&quot;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            //用户已经登录，并且访问其它页面，则运行访问</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          //用户没有登录,并且访问的就是登录页，则运行访问登录页</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          if (to.path === &quot;/login&quot;) &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next();</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125; else &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            //用户没有登录，访问其它页面，则跳转到登录页面。</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            next(&quot;/login?redirect=&quot; + to.fullPath);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        router,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>当然，项目的目录结构做了一定的调整，如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E7%9B%AE%E5%BD%95.png" alt="image-20200826223502724"></p>
<p>在<code>web</code>目录下面，存放的是<code>index.html</code>,在<code>webserver</code>目录下面存放的是<code>node</code>代码。</p>
<p>下面看一下具体的<code>node</code>代码的实现。</p>
<p>app.js 文件中的代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>);</span><br><span class="line"><span class="comment">//导入处理history模式的模块</span></span><br><span class="line"><span class="keyword">const</span> history = <span class="built_in">require</span>(<span class="string">&quot;connect-history-api-fallback&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&quot;express&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">express</span>();</span><br><span class="line"><span class="comment">//注册处理history模式的中间件</span></span><br><span class="line"><span class="comment">// app.use(history())</span></span><br><span class="line"><span class="comment">//处理静态资源的中间件,处理web目录下的index.html</span></span><br><span class="line">app.<span class="title function_">use</span>(express.<span class="title function_">static</span>(path.<span class="title function_">join</span>(__dirname, <span class="string">&quot;../web&quot;</span>)));</span><br><span class="line">app.<span class="title function_">listen</span>(<span class="number">3000</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;服务器开启&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p><code>connect-history-api-fallback</code>模块的安装如下(注意在上面的代码中还没有使用该模块)</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">npm install --save connect-history-api-fallback</span><br></pre></td></tr></table></figure>

<p>下面还需要安装<code>express</code></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">npm install express</span><br></pre></td></tr></table></figure>

<p>启动服务</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">node app.js</span><br></pre></td></tr></table></figure>

<p>现在在地址栏中输入:<code>http://localhost:3000</code>就可以访问网站了。</p>
<p>并且当我们去单击左侧的菜单的时候，可以实现页面的切换，同时单击“关于”的时候，会出现<code>NotFound</code>组件中的内容。</p>
<p>经过测试发现好像没有什么问题，那这是什么原因呢？你想一下当我们单击左侧菜单的时候，路由是怎样工作的呢？</p>
<p>因为现在我们开启了路由的<code>history</code>模式，而该模式是通过<code>HTML5</code>中的<code>history</code>中的<code>api</code>来完成路由的操作的，也就是当我们单击菜单的时候，是通过<code>history.pushState( ) </code>方法来修改地址栏中的地址，实现组件的切换，而且还会把地址保存的历史记录中（也就是可以单击浏览器中后退按钮，实现后退等操作），但是它并不会向服务器发送请求。</p>
<p>所以说现在整个操作都是在客户端完成的。</p>
<p>但是，当我刷新了浏览器以后，会出现怎样的情况呢？</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E8%AF%B7%E6%B1%82.png" alt="image-20200826224843519"></p>
<p>上图的含义就是，当单击浏览器中的刷新按钮的时候，会向服务器发送请求，要求<code>node</code>服务器处理这个地址，但是服务器并没有处理该地址，所以服务器会返回<code>404</code></p>
<p>以上就是如果<code>vue-router</code>开启了<code>history</code>模式后，出现的问题。</p>
<p>下面解决这个问题，在服务端启用<code>connect-history-api-fallback</code>模块就可以了，如下代码所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>);</span><br><span class="line"><span class="comment">//导入处理history模式的模块</span></span><br><span class="line"><span class="keyword">const</span> history = <span class="built_in">require</span>(<span class="string">&quot;connect-history-api-fallback&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&quot;express&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">express</span>();</span><br><span class="line"><span class="comment">//注册处理history模式的中间件</span></span><br><span class="line">app.<span class="title function_">use</span>(<span class="title function_">history</span>());</span><br><span class="line"><span class="comment">//处理静态资源的中间件</span></span><br><span class="line">app.<span class="title function_">use</span>(express.<span class="title function_">static</span>(path.<span class="title function_">join</span>(__dirname, <span class="string">&quot;../web&quot;</span>)));</span><br><span class="line">app.<span class="title function_">listen</span>(<span class="number">3000</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;服务器开启&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>服务端的代码做了修改以后，一定要服务端重新启动<code>node app.js</code></p>
<p>然后经过测试以后发现没有问题了。</p>
<p>那么现在你考虑一下，具体的工作方式是什么？</p>
<p>当我们在服务端开启对<code>history</code>模式的支持以后，我们刷新浏览器，会想服务器发送请求，例如:<code>http://localhost:3000/orders</code></p>
<p>服务器接收该请求，那么用于服务器开启了<code>history</code>模式，然后服务器会检查，根据该请求所访问的页面是不存在的，所以会将单页面应用的<code>index.html</code>返回给浏览器。浏览器接收<code>index.html</code>页面后，会判断路由地址，发现地址为<code>orders</code>,所以会加载该地址对应的组件内容。</p>
<h3 id="13-3-在-Nginx-服务器中配置History模式"><a href="#13-3-在-Nginx-服务器中配置History模式" class="headerlink" title="13.3 在 Nginx 服务器中配置History模式"></a>13.3 在 Nginx 服务器中配置<code>History</code>模式</h3><p><strong>代理服务器</strong></p>
<p><strong>代理服务器</strong>:一般是指局域网内部的机器通过代理服务器发送请求到互联网上的服务器,代理服务器一般作用在客户端。应用比如：GoAgent，翻墙神器.</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/1566823356428.png"></p>
<p><strong>反向代理服务器</strong></p>
<p><strong>反向代理服务器：</strong>在服务器端接受客户端的请求，然后把请求分发给具体的服务器进行处理，然后再将服务器的响应结果反馈给客户端。Nginx 就是其中的一种反向代理服务器软件。</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/1566823580536.png"></p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/1566823650555.png"></p>
<p><strong>Nginx 简介</strong></p>
<p>Nginx (“engine x”) ，Nginx (“engine x”) 是俄罗斯人 Igor Sysoev(塞索耶夫)编写的一款高性能的 HTTP 和反向代理服务器。也是一个 IMAP&#x2F;POP3&#x2F;SMTP 代理服务器；也就是说，Nginx 本身就可以托管网站，进行 HTTP 服务处理，也可以作为反向代理服务器使用。</p>
<p><strong>Nginx 的应用现状</strong></p>
<p>淘宝、新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz!、水木社区、豆瓣、YUPOO、海内、迅雷在线 等多家网站使用 Nginx 作为 Web 服务器或反向代理服务器。</p>
<p><strong>Nginx 的特点</strong></p>
<ul>
<li><p><strong>跨平台：</strong>Nginx 可以在大多数 Unix like OS 编译运行，而且也有 Windows 的移植版本。</p>
</li>
<li><p><strong>配置异常简单：</strong>非常容易上手。配置风格跟程序开发一样，神一般的配置</p>
</li>
<li><p><strong>非阻塞、高并发连接：</strong>数据复制时，磁盘 I&#x2F;O 的第一阶段是非阻塞的。官方测试能够支撑 5 万并发连接，在实际生产环境中跑到 2 ～ 3 万并发连接数.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">  高并发：其实就是使用技术手段使得系统可以并行处理很多的请求！衡量指标常用的有响应时间，吞吐量，每秒查询率QPS，并发用户数。响应时间：系统对请求做出响应的时间。你简单理解为一个http请求返回所用的时间。</span><br><span class="line"></span><br><span class="line">吞吐量：单位时间内处理的请求数量。</span><br><span class="line"></span><br><span class="line">QPS：每秒可以处理的请求数</span><br><span class="line"></span><br><span class="line">并发用户数：同时承载正常使用系统功能的用户数量。也就是多少个人同时使用这个系统，这个系统还能正常运行。这个用户数量就是并发用户数了</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>内存消耗小：</strong>处理大并发的请求内存消耗非常小。在 3 万并发连接下，开启的 10 个 Nginx 进程才消耗 150M 内存（15M*10&#x3D;150M）。</p>
</li>
<li><p><strong>成本低廉：</strong>Nginx 为开源软件，可以免费使用。而购买 F5 BIG-IP、NetScaler 等硬件负载均衡交换机则需要十多万至几十万人民币 。</p>
</li>
<li><p><strong>内置的健康检查功能：</strong>如果 Nginx Proxy 后端的某台 Web 服务器宕机了，不会影响前端访问。</p>
</li>
</ul>
<p><strong>节省带宽：</strong>支持 GZIP 压缩，可以添加浏览器本地缓存的 Header 头。</p>
<p><strong>稳定性高：</strong>用于反向代理，宕机的概率微乎其微</p>
<p><strong>Nginx 启动</strong></p>
<ul>
<li><p>到官网下载 Windows 版本，下载地址：<a target="_blank" rel="noopener" href="http://nginx.org/en/download.html">http://nginx.org/en/download.html</a></p>
</li>
<li><p>解压到磁盘任一目录（<strong>注意：nginx 解压后的文件夹不能放在中文目录下。</strong>）</p>
</li>
<li><p>修改配置文件</p>
</li>
<li><p>启动服务：</p>
<p>•直接运行 nginx.exe</p>
</li>
</ul>
<p>Nginx 服务器默认占用的是 80 端口号，而在 window10 中端口号 80 已经被其它的应用程序占用，所以这里可以修改一下 Nginx 的端口号，在 conf 目录下找到 nginx.conf 文件，该文件就是 Nginx 服务的配置文件，通过该配置文件可以修改 Nginx 的端口号，当然后期针对 Nginx 服务器的配置都是通过该文件完成的。</p>
<p>在这里，我将端口号修改成了:8081,所以在浏览器的地址栏中，输入：<a target="_blank" rel="noopener" href="http://localhost:8081/">http://localhost:8081</a> 可以打开默认的欢迎页面，表示 Nginx 服务启动成功。</p>
<p>下面我们要做的就是将我们的程序部署到<code>Nginx</code>中。</p>
<p>现在，我们可以将做好的网站页面拷贝到<code>Nginx</code>中的<code>html</code>目录中，然后在地址栏中输入：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">http://localhost:8081/</span><br></pre></td></tr></table></figure>

<p>就可以看到对应的页面了，然后单击菜单，发现可以进行留有的切换。当单击刷新按钮后，发现出现了 404 的错误。</p>
<p>原因，点击刷新按钮就会向服务器发送请求，而在服务端没有对应的文件，所以会出现 404 的错误。</p>
<p>下面我们需要对<code>Nginx</code>服务器进行配置，找到<code>conf</code>目录下的<code>nginx.conf</code>.</p>
<p>然后进行如下的配置：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">location / &#123;</span><br><span class="line">           root   html;</span><br><span class="line">           index  index.html index.htm;</span><br><span class="line">		try_files $uri $uri/ /index.html;</span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure>

<p>当在地址栏中输入<code>/</code>的时候，会请求根目录也就是<code>html</code>目录中的<code>index.html</code>.</p>
<p>现在，我们又加了<code>try_files</code>配置，表示尝试访问文件。</p>
<p><code>$uri</code>表示根据所请求的<code>url</code>地址查找对应文件，如果找到了返回，没有找到。</p>
<p>将<code>$uri</code>作为目录，查找该目录下的<code>index.html</code>,如果找到就返回，没有找到，则直接返回<code>html</code>目录下面的<code>index.html</code>文件。</p>
<p>而现在我们已经将我们做好的页面拷贝到了<code>html</code>目录下面，所以直接将我们的页面返回了。</p>
<p>下面可以进行测试。</p>
<p>测试之前需要重新启动服务器。</p>
<p>打开<code>cmd</code>，然后定位到<code>Nginx</code>的目录，输入以下命令重新启动服务器。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">nginx -s reload</span><br></pre></td></tr></table></figure>

<p>这时的执行流程是：当单击浏览器中的刷新按钮后，会向服务器发送请求，服务接收到请求后，发现没有所访问的文件，但是，由于我们配置了<code>try_files</code>,所以会将<code>html</code>目录下面的<code>index.html</code>页面的内容返回，返回给浏览器后，浏览器会根据路由来进行处理，也就是查找对应组件进行渲染。</p>
<h1 id="二、Vue-Router-原理"><a href="#二、Vue-Router-原理" class="headerlink" title="二、Vue Router 原理"></a>二、Vue Router 原理</h1><p>现在我们已经掌握了<code>Vue Router</code>的基本使用，下面我们来模拟<code>Vue Router</code>的实现，通过模拟实现，来了解其内部的实现原理。</p>
<p>我们这里模拟的是<code>History</code>模式。<code>Hash</code>模式基本实现上是一样的。</p>
<p>这里先来复习一下<code>Hash</code>模式的工作原理。</p>
<ul>
<li>·<code>URL</code>中<code>#</code>后面的内容作为路径地址，当地址改变的时候不会向服务器发送请求，但是会触发<code>hashchange</code>事件。</li>
<li>监听<code>hashchange</code>事件，在该事件中记录当前的路由地址，然后根据路由地址找到对应组件。</li>
<li>根据当前路由地址找到对应组件重新渲染。</li>
</ul>
<p>下面再来复习一下<code>History</code>模式</p>
<ul>
<li>通过<code>history.pushState()</code>方法改变地址栏，并且将当前地址记录到浏览器的历史记录中。当前浏览器不会向服务器发送请求</li>
<li>监听<code>popstate</code>事件，可以发现浏览器历史操作的变化，记录改变后的地址，单击前进或者是后退按钮的时候触发该事件</li>
<li>根据当前路由地址找到对应组件重新渲染</li>
</ul>
<h2 id="1、分析-Vue-Router"><a href="#1、分析-Vue-Router" class="headerlink" title="1、分析 Vue Router"></a>1、分析 Vue Router</h2><p>在模拟<code>Vue Router</code>之前，</p>
<p>首先来看一下<code>Vue Router</code>的核心代码，做一个简单的分析</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//注册插件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">VueRouter</span>);</span><br><span class="line"><span class="comment">//创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [&#123; <span class="attr">name</span>: <span class="string">&quot;home&quot;</span>, <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">component</span>: homeComponent &#125;],</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 创建Vue实例，注册router对象</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  router,</span><br><span class="line">  <span class="attr">render</span>: <span class="function">(<span class="params">h</span>) =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>),</span><br><span class="line">&#125;).$mount(<span class="string">&quot;#apps&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>我们知道<code>Vue Router</code>是<code>Vue</code>的插件，所以在上面的代码中，我们首先调用<code>use</code>方法注册该插件。</p>
<p><code>use</code>方法需要的参数可以是一个函数或者是对象，如果传递的是函数，<code>use</code>内部会直接调用该函数，</p>
<p>如果传递的是一个对象，那么在<code>use</code>内部会调用该对象的<code>install</code>方法。</p>
<p>而我们这里传递的是对象，所以后面在模拟<code>VUe Router</code>的时候，要实现一个<code>install</code></p>
<p>方法。</p>
<p>下面我们创建了<code>VueRouter</code>实例，所以<code>VueRouter</code>可以是构造方法或者是类，那么我们在模拟的时候，将其定义为类。并且该类中有一个静态的<code>install</code>方法，因为我们将<code>VueRouter</code>传递给了<code>use</code>方法。</p>
<p>在<code>VueRouter</code>类的构造方法中，需要有一个参数，该参数是一个对象，该对象中定义了路由的规则。</p>
<p>最后创建了<code>Vue</code>的实例，并且将创建好的<code>Vue Router</code>对象传递到该实例中。</p>
<p>下面我们在看一下<code>Vue Router</code>的类图</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E7%B1%BB%E5%9B%BE.png"></p>
<p>在该类图中，上半部分是<code>VueRouter</code>的属性，而下半部分是<code>VueRouter</code>的方法。</p>
<p><code>options</code>作用是记录构造函数中传入的对象, 我们在创建<code>Vue Router</code>的实例的时候，传递了一个对象，而该对象中定义了路由规则。而<code>options</code>就是记录传入的这个对象的。</p>
<p><code>routeMap</code>:是一个对象，记录路由地址与组件的对应关系，也就是一个键值对的形式，后期会 options 中路由规则解析到<code>routeMap</code>中。</p>
<p><code>data</code>是一个对象，该对象中有一个属性<code>current</code>,该属性用来记录当前的路由地址，<code>data</code>是一个响应式的对象，因为当前路由地址发生变化后，对应的组件要发生更新（_也就说当地址变化后，要加载对应组件_）。</p>
<p><code>install</code>是一个静态方法，用来实现<code>Vue</code>的插件机制。</p>
<p><code>Constructor</code>是一个构造方法，该该构造方法中会初始化<code>options</code> ,<code>data</code>,<code>routeMap</code>这几个属性。</p>
<p><code>inti</code>方法主要是用来调用下面的三个方法，也就把不同的代码分隔到不同的方法中去实现。</p>
<p><code>initEvent</code>方法，用来注册<code>popstate</code>事件，</p>
<p><code>createRouteMap</code>方法，该方法会把构造函数中传入进来的路由规则，转换成键值对的形式存储到<code>routeMap</code>中。 键就是路由的地址，值就是对应的组件</p>
<p><code>initComponents</code>方法，主要作用是用来创建<code>router-link</code>和<code>router-view</code>这两个组件的。</p>
<p>现在我们已经对<code>Vue Router</code>做了一个分析。</p>
<p>下面开始创建自己的<code>Vue Router</code>.</p>
<h2 id="2、install-方法实现"><a href="#2、install-方法实现" class="headerlink" title="2、install 方法实现"></a>2、install 方法实现</h2><p>在<code>vue_router_app</code>项目的<code>src</code>目录下面创建一个<code>vuerouter</code>目录，同时创建一个<code>index.js</code>文件，在该文件中创建如下的代码。</p>
<p><code>install</code>方法需要的参数是<code>Vue</code>的构造方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> _Vue = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">VueRouter</span> &#123;</span><br><span class="line">  <span class="comment">//调用install方法的时候，会传递Vue的构造函数</span></span><br><span class="line">  <span class="keyword">static</span> <span class="title function_">install</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">    <span class="comment">//首先判断插件是否已经被安装，如果已经被安装，就不需要重复安装。</span></span><br><span class="line">    <span class="comment">//1、判断当前插件是否已经被安装:</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="title class_">VueRouter</span>.<span class="property">install</span>.<span class="property">installed</span>) &#123;</span><br><span class="line">      <span class="comment">//条件成立，表明插件已经被安装，什么都不要做。</span></span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title class_">VueRouter</span>.<span class="property">install</span>.<span class="property">installed</span> = <span class="literal">true</span>;</span><br><span class="line">    <span class="comment">//2、把Vue构造函数记录到全局变量中。</span></span><br><span class="line">    _Vue = <span class="title class_">Vue</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//3、把创建Vue实例时候传入的router对象注入到Vue实例上。</span></span><br><span class="line">    _Vue.<span class="title function_">mixin</span>(&#123;</span><br><span class="line">      <span class="title function_">beforeCreate</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">//在创建Vue实例的时候</span></span><br><span class="line">        <span class="comment">// 也就是new Vue()的时候，才会有$options这个属性，</span></span><br><span class="line">        <span class="comment">//组件中是没有$options这个属性的。</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>) &#123;</span><br><span class="line">          _Vue.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$router</span> = <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3、实现构造函数"><a href="#3、实现构造函数" class="headerlink" title="3、实现构造函数"></a>3、实现构造函数</h2><p>在介绍<code>VueRouter</code>的类图时，我们说过</p>
<p><code>Constructor</code>是一个构造方法，该该构造方法中会初始化<code>options</code> ,<code>data</code>,<code>routeMap</code>这几个属性。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">constructor</span>(<span class="params">options</span>) &#123;</span><br><span class="line"></span><br><span class="line">   <span class="variable language_">this</span>.<span class="property">options</span> = options;</span><br><span class="line"></span><br><span class="line">   <span class="variable language_">this</span>.<span class="property">routeMap</span> = &#123;&#125;;</span><br><span class="line"></span><br><span class="line">   <span class="variable language_">this</span>.<span class="property">data</span> = _Vue.<span class="title function_">observable</span>(&#123;</span><br><span class="line">     <span class="attr">current</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<h2 id="4、createRouteMap-方法实现"><a href="#4、createRouteMap-方法实现" class="headerlink" title="4、createRouteMap 方法实现"></a>4、createRouteMap 方法实现</h2><p><code>createRouteMap</code>方法，该方法会把构造函数中传入进来的<code>options</code>参数中的路由规则，转换成键值对的形式存储到<code>routeMap</code>中。 键就是路由的地址，值就是对应的组件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">createRouteMap</span>(<span class="params"></span>) &#123;</span><br><span class="line"></span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">options</span>.<span class="property">routes</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">route</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">routeMap</span>[route.<span class="property">path</span>] = route.<span class="property">component</span>;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="5、initComponents-方法实现"><a href="#5、initComponents-方法实现" class="headerlink" title="5、initComponents 方法实现"></a>5、initComponents 方法实现</h2><p><code>initComponents</code>方法，主要作用是用来创建<code>router-link</code>和<code>router-view</code>这两个组件的。</p>
<p>下面先在这个方法中创建<code>router-link</code>这个组件。</p>
<p>先来看一下<code>router-link</code>这个组件的基本使用</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;router-link to=&quot;/users&quot;&gt; 用户管理&lt;/router-link&gt;</span><br></pre></td></tr></table></figure>

<p>我们知道，<code>router-link</code>这个组件最终会被渲染成<code>a</code>标签，同时<code>to</code>作为一个属性，其值会作为<code>a</code>标签中的<code>href</code>属性的值。同时还要获取<code>&lt;router-link&gt;</code>这个组件中的文本，作为最终超链接的文本。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">initComponents</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-link&quot;</span>, &#123;</span><br><span class="line">     <span class="attr">props</span>: &#123;</span><br><span class="line">       <span class="attr">to</span>: <span class="title class_">String</span>,</span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="attr">template</span>: <span class="string">&#x27;&lt;a :href=&quot;to&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/a&gt;&#x27;</span>,</span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们通过<code>Vue.component</code>来创建<code>router-link</code>这个组件，同时通过<code>props</code>接收<code>to</code>属性传递过来的值，并且对应的类型为字符串。</p>
<p>最终渲染的模板是一个<code>a</code>标签，<code>href</code>属性绑定了<code>to</code>属性的值，同时使用<code>&lt;slot&gt;</code>插槽作为占位符，用具体的文字内容填充该占位符。</p>
<p>现在已经将<code>router-link</code>这个组件创建好了。</p>
<p>下面我们需要对我们写的这些代码进行测试。</p>
<p>要进行测试应该先将<code>createRouteMap</code>方法与<code>initComponents</code>方法都调用一次，那么问题是</p>
<p>在什么时候调用这两个方法呢？</p>
<p>我们可以在 VueRoute 对象创建成功后，并且将<code>VueRouter</code>对象注册到<code>Vue</code>的实例上的时候，调用这两个方法。</p>
<p>也就是在<code>beforeCreate</code>这个钩子函数中。</p>
<p>当然为了调用这两个方便，在这里我们又定义了<code>init</code>方法，来做了一次封装处理。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">init</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">this</span>.<span class="title function_">createRouteMap</span>();</span><br><span class="line">  <span class="variable language_">this</span>.<span class="title function_">initComponents</span>(_Vue);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>对<code>init</code>方法的调用如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">beforeCreate</span>(<span class="params"></span>) &#123;</span><br><span class="line">     <span class="comment">//在创建Vue实例的时候</span></span><br><span class="line">     <span class="comment">// 也就是new Vue()的时候，才会有$options这个属性，</span></span><br><span class="line">     <span class="comment">//组件中是没有$options这个属性的。</span></span><br><span class="line">     <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>) &#123;</span><br><span class="line">       _Vue.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$router</span> = <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>;</span><br><span class="line">         <span class="comment">//调用init</span></span><br><span class="line">       <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>.<span class="title function_">init</span>();</span><br><span class="line">     &#125;</span><br><span class="line">   &#125;,</span><br></pre></td></tr></table></figure>

<p><code> this.$options.router.init();</code></p>
<p>这句代码的含义：<code>this</code>表示的就是 Vue 实例，<code>$options</code>表示的就是在创建<code>Vue</code>的实例的时候传递的选项，如下所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">  router,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>通过上面的代码，我们可以看到，传递过来的选项中是有<code>router</code>.</p>
<p>而这个<code>router</code>是什么呢？</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;&#125;）</span><br></pre></td></tr></table></figure>

<p>就是<code>VueRouter</code>这个类的实例。而我们当前自己所模拟的路由,所创建的类就叫做<code>VueRouter</code>（也就是以后在创建路由实例的时候，使用我们自己创建的<code>VueRouter</code>这个类来完成）.</p>
<p>而<code>init</code>方法就是<code>VueRouter</code>这个类的实例方法。所以可以通过<code>this.$options.router.init()</code>的方式来调用。</p>
<p>下面我们来测试一下。</p>
<p>在<code>vue_router_app</code>项目的<code>src</code>目录下面，创建<code>router.js</code>文件,文件定义路由规则.</p>
<p>如下代码所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="comment">// import Router from &quot;vue-router&quot;;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Router</span> <span class="keyword">from</span> <span class="string">&quot;./vuerouter&quot;</span>; <span class="comment">//注意:这里导入的是自己定义的路由规则</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Login</span> <span class="keyword">from</span> <span class="string">&quot;./components/Login.vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Home</span> <span class="keyword">from</span> <span class="string">&quot;./components/Home.vue&quot;</span>;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Router</span>);</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Router</span>(&#123;</span><br><span class="line">  <span class="attr">model</span>: <span class="string">&quot;history&quot;</span>,</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">component</span>: <span class="title class_">Home</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/login&quot;</span>, <span class="attr">component</span>: <span class="title class_">Login</span> &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在<code>components</code>目录下面分别创建<code>Home.vue</code>与<code>Login.vue</code>.</p>
<p><code>Home.vue</code> 的代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;router-link to=&quot;/login&quot;&gt;登录&lt;/router-link&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p><code>Login.vue</code>的代码如下:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;登录页面&lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;&#125;;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p><code>App.vue</code>组件的内容如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">    &lt;div id=&quot;nav&quot;&gt;</span><br><span class="line">      &lt;router-link to=&quot;/&quot;&gt;Home&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link to=&quot;/login&quot;&gt;Login&lt;/router-link&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p>在<code>main.js</code> 中完成路由的注册。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&quot;./App.vue&quot;</span>;</span><br><span class="line"><span class="comment">//导入router.js</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&quot;./router&quot;</span>;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">productionTip</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  router,</span><br><span class="line">  <span class="attr">render</span>: <span class="function">(<span class="params">h</span>) =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>),</span><br><span class="line">&#125;).$mount(<span class="string">&quot;#app&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>运行上面的代码会出现如下的错误：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/%E9%94%99%E8%AF%AF.png"></p>
<p>第二个错误是我们还没有创建<code>router-view</code>这个组件，所以才会出现该错误。这里暂时可以先不用考虑。</p>
<p>主要是第一个错误，该错误的含义是，目前我们使用的是运行时版本的<code>Vue</code>, 模板编译器不可用。</p>
<p>你可以使用预编译把模板编译成<code>render</code>函数，或者是使用包含编译版本的<code>Vue</code>.</p>
<p>以上错误说明了<code>Vue</code>的构建版本有两个，分别是“运行时版”和”完整版”.</p>
<p>运行时版：不支持<code>template</code>模板，需要打包的时候提前编译。</p>
<p>完整版：包含运行时和编译器，体积比运行时版大<code>10k</code>左右，程序运行的时候把模板转换成<code>render</code>函数。性能低于运行时版本。</p>
<p>使用<code>vue-cli</code>创建的项目默认为<code>运行时版本</code>,而我们创建的<code>VueRouter</code>类中有<code>template</code>模板，所以才会出现第一个错误。</p>
<p>官方文档：<code>https://cn.vuejs.org/v2/guide/installation.html</code></p>
<p>下面我们看一下解决方案：</p>
<p>在前面我们已经提到过，使用<code>vue-cli</code> 创建的项目是运行时项目，所以没有编译器，如果我们将其修改成完整版，就有编译器，对模板进行编译。</p>
<p>解决的方案：在项目的根目录创建<code>vue.config.js</code>文件，在该文件中添加<code>runtimeCompiler</code>配置项，该配置项表示的是，是否使用包含运行时编译器的<code>Vue</code>构建</p>
<p>版本（完整版）。设置为<code>true</code>后你就可以在<code>Vue</code>组件中使用<code>template</code>选项了，但是这会让你的应用额外增加<code>10kb</code>左右。默认该选项的取值为<code>false</code>.</p>
<p><code>vue.config.js</code>文件配置如下</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">runtimeCompiler</span>: <span class="literal">true</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>表示使用的是完整版，这时编译器会将<code>template</code>选项转换成<code>render</code>函数。</p>
<p>注意：要想以上配置内容起作用，必须重新启动服务器。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">npm run serve</span><br></pre></td></tr></table></figure>

<h2 id="6、render函数"><a href="#6、render函数" class="headerlink" title="6、render函数"></a>6、<code>render</code>函数</h2><p>虽然使用完整版<code>Vue</code>可以解决上面的问题，但是由于带有编译器，体积比运行时版本大<code>10k</code>左右，所以性能比运行时版要低。</p>
<p>那么这一小节我们使用运行时版本来解决这个问题。</p>
<p>我们知道，完整版中的编译器的作用就是将<code>template</code>模板转成<code>render</code>函数，所以在运行时版本中我们可以自己编写<code>render</code>函数。</p>
<p>但是在这你肯定也有一个问题，就是在单文件组件中，我们一直都是在写<code>&lt;template&gt;&lt;/template&gt;</code>,并且没有写<code>render</code>函数，</p>
<p>但是为什么能够正常的工作呢？这时因为在打包的时候，将<code>&lt;template&gt;</code>编译成了<code>render</code>函数，这就是预编译。</p>
<p>最终代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//该方法需要一个参数为Vue的构造函数。</span></span><br><span class="line"> <span class="comment">//当然也可以使用全局的_Vue.</span></span><br><span class="line"> <span class="title function_">initComponents</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-link&quot;</span>, &#123;</span><br><span class="line">     <span class="attr">props</span>: &#123;</span><br><span class="line">       <span class="attr">to</span>: <span class="title class_">String</span>,</span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="comment">// template: &#x27;&lt;a :href=&quot;to&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/a&gt;&#x27;,</span></span><br><span class="line">     <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">         <span class="string">&quot;a&quot;</span>,</span><br><span class="line">         &#123;</span><br><span class="line">           <span class="attr">attrs</span>: &#123;</span><br><span class="line">             <span class="attr">href</span>: <span class="variable language_">this</span>.<span class="property">to</span>,</span><br><span class="line">           &#125;,</span><br><span class="line">         &#125;,</span><br><span class="line">         [<span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span>]</span><br><span class="line">       );</span><br><span class="line">     &#125;,</span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>注意：在测试之前一定要将根目录下的<code>vue.config.js</code>文件删除掉，这样当前的环境为“运行时”环境。</p>
<h2 id="7、创建router-view组件"><a href="#7、创建router-view组件" class="headerlink" title="7、创建router-view组件"></a>7、创建<code>router-view</code>组件</h2><p><code>router-view</code>组件就是一个占位符。当根据路由规则找到组件后，会渲染到<code>router-view</code>的位置。</p>
<p>在<code>initComponents</code>方法中创建<code>router-view</code>组件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//该方法需要一个参数为Vue的构造函数。</span></span><br><span class="line"> <span class="comment">//当然也可以使用全局的_Vue.</span></span><br><span class="line"> <span class="title function_">initComponents</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-link&quot;</span>, &#123;</span><br><span class="line">     <span class="attr">props</span>: &#123;</span><br><span class="line">       <span class="attr">to</span>: <span class="title class_">String</span>,</span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="comment">// template: &#x27;&lt;a :href=&quot;to&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/a&gt;&#x27;,</span></span><br><span class="line">     <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">         <span class="string">&quot;a&quot;</span>,</span><br><span class="line">         &#123;</span><br><span class="line">           <span class="attr">attrs</span>: &#123;</span><br><span class="line">             <span class="attr">href</span>: <span class="variable language_">this</span>.<span class="property">to</span>,</span><br><span class="line">           &#125;,</span><br><span class="line">         &#125;,</span><br><span class="line">         [<span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span>]</span><br><span class="line">       );</span><br><span class="line">     &#125;,</span><br><span class="line">   &#125;);</span><br><span class="line">   <span class="keyword">const</span> self = <span class="variable language_">this</span>;<span class="comment">//修改this的指向</span></span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-view&quot;</span>, &#123;</span><br><span class="line">     <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">       <span class="comment">//根据当前的路径从routeMap中查找对应的组件.</span></span><br><span class="line">       <span class="keyword">const</span> component = self.<span class="property">routeMap</span>[self.<span class="property">data</span>.<span class="property">current</span>];</span><br><span class="line">       <span class="comment">//将组件转换成虚拟dom</span></span><br><span class="line">       <span class="keyword">return</span> <span class="title function_">h</span>(component);</span><br><span class="line">     &#125;,</span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>下面，我们可以测试一下效果。</p>
<p>当我们单击链接的时候，发现了浏览器进行了刷新操作。表明向服务器发送了请求，而我们单页面应用中是不希望向服务器发送请求。</p>
<p>修改后的<code>initComponents</code>方法如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//该方法需要一个参数为Vue的构造函数。</span></span><br><span class="line"> <span class="comment">//当然也可以使用全局的_Vue.</span></span><br><span class="line"> <span class="title function_">initComponents</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-link&quot;</span>, &#123;</span><br><span class="line">     <span class="attr">props</span>: &#123;</span><br><span class="line">       <span class="attr">to</span>: <span class="title class_">String</span>,</span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="comment">// template: &#x27;&lt;a :href=&quot;to&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/a&gt;&#x27;,</span></span><br><span class="line">     <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">         <span class="string">&quot;a&quot;</span>,</span><br><span class="line">         &#123;</span><br><span class="line">           <span class="attr">attrs</span>: &#123;</span><br><span class="line">             <span class="attr">href</span>: <span class="variable language_">this</span>.<span class="property">to</span>,</span><br><span class="line">           &#125;,</span><br><span class="line">           <span class="attr">on</span>: &#123;</span><br><span class="line">             <span class="attr">click</span>: <span class="variable language_">this</span>.<span class="property">clickHandler</span>,</span><br><span class="line">           &#125;,</span><br><span class="line">         &#125;,</span><br><span class="line">         [<span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span>]</span><br><span class="line">       );</span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="attr">methods</span>: &#123;</span><br><span class="line">       <span class="title function_">clickHandler</span>(<span class="params">e</span>) &#123;</span><br><span class="line"></span><br><span class="line">         history.<span class="title function_">pushState</span>(&#123;&#125;, <span class="string">&quot;&quot;</span>, <span class="variable language_">this</span>.<span class="property">to</span>);</span><br><span class="line"></span><br><span class="line">         <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="property">data</span>.<span class="property">current</span> = <span class="variable language_">this</span>.<span class="property">to</span>;</span><br><span class="line"></span><br><span class="line">         <span class="comment">//阻止向服务器发送器。</span></span><br><span class="line">         e.<span class="title function_">preventDefault</span>();</span><br><span class="line">       &#125;,</span><br><span class="line">     &#125;,</span><br><span class="line">   &#125;);</span><br><span class="line">   <span class="keyword">const</span> self = <span class="variable language_">this</span>;</span><br><span class="line">   <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;router-view&quot;</span>, &#123;</span><br><span class="line">     <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">       <span class="comment">//根据当前的路径从routeMap中查找对应的组件.</span></span><br><span class="line">       <span class="keyword">const</span> component = self.<span class="property">routeMap</span>[self.<span class="property">data</span>.<span class="property">current</span>];</span><br><span class="line">       <span class="comment">//将组件转换成虚拟dom</span></span><br><span class="line">       <span class="keyword">return</span> <span class="title function_">h</span>(component);</span><br><span class="line">     &#125;,</span><br><span class="line">   &#125;);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>给<code>a</code>标签添加了单击事件。</p>
<h2 id="8、initEvent方法实现"><a href="#8、initEvent方法实现" class="headerlink" title="8、initEvent方法实现"></a>8、<code>initEvent</code>方法实现</h2><p>现在有一个问题就是，当点击浏览器中的后退与前进按钮的时候，地址栏中的地址发生了变化，但是对应的组件没有发生变化。</p>
<p>这时候要解决这个问题， 就需要用到<code>popstate</code>事件</p>
<p><code>popstate</code>事件，可以发现浏览器历史操作的变化，记录改变后的地址，单击前进或者是后退按钮的时候触发该事件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">initEvent</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;popstate&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">data</span>.<span class="property">current</span> = <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">pathname</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>针对<code>initEvent</code>方法的调用如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">init</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">createRouteMap</span>();</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">initComponents</span>(_Vue);</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">initEvent</span>();</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<h1 id="三、VueRouter-模拟实现与源码解读"><a href="#三、VueRouter-模拟实现与源码解读" class="headerlink" title="三、VueRouter 模拟实现与源码解读"></a>三、VueRouter 模拟实现与源码解读</h1><p>在第二章中，我们已经对<code>VueRouter</code>做了一个基本的实现，通过这个基本的实现，已经对<code>VueRouter</code>的原理有了一个基本的理解。</p>
<p>但是，我们并没有实现路由嵌套的形式，这次我们重点来实现这一点。</p>
<h2 id="1、Vue-use-源码"><a href="#1、Vue-use-源码" class="headerlink" title="1、Vue.use( )源码"></a>1、<code>Vue.use( )</code>源码</h2><p>源码位置：<code>vue/src/core/global-api/use.js</code></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">initUse</span>(<span class="params">Vue: GlobalAPI</span>) &#123;</span><br><span class="line">  <span class="comment">//use方法的参数接收的是一个插件，该插件的类型可以是一个函数，也可以是一个对象</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="property">use</span> = <span class="keyword">function</span> (<span class="params">plugin: <span class="built_in">Function</span> | <span class="built_in">Object</span></span>) &#123;</span><br><span class="line">    <span class="comment">//_installedPlugins数组中存放已经安装的插件。</span></span><br><span class="line">    <span class="keyword">const</span> installedPlugins =</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">_installedPlugins</span> || (<span class="variable language_">this</span>.<span class="property">_installedPlugins</span> = []);</span><br><span class="line">    <span class="comment">//判断一下传递过来的插件是否在installedPlugins中存在，如果存在，则直接返回</span></span><br><span class="line">    <span class="keyword">if</span> (installedPlugins.<span class="title function_">indexOf</span>(plugin) &gt; -<span class="number">1</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// additional parameters</span></span><br><span class="line">    <span class="comment">//将arguments转换成数组，并且将数组中的第一项去除。</span></span><br><span class="line">    <span class="keyword">const</span> args = <span class="title function_">toArray</span>(<span class="variable language_">arguments</span>, <span class="number">1</span>);</span><br><span class="line">    <span class="comment">//把this(也就是Vue，这里是通过Vue.use来调用的)插入到数组中的第一个元素的位置。</span></span><br><span class="line">    args.<span class="title function_">unshift</span>(<span class="variable language_">this</span>);</span><br><span class="line">    <span class="comment">//这时plugin是一个对象，看一下是否有install这个函数。</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> plugin.<span class="property">install</span> === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">      <span class="comment">//如果有install这个函数，直接调用</span></span><br><span class="line">      <span class="comment">//这里通过apply将args数组中的每一项展开传递给install这个函数。</span></span><br><span class="line">      <span class="comment">// plugin.install(args[0],args[1])</span></span><br><span class="line">      <span class="comment">//而args[0],就是上面我们所插入的Vue.这一点与我们前面在模拟install方法的时候是一样的。</span></span><br><span class="line">      plugin.<span class="property">install</span>.<span class="title function_">apply</span>(plugin, args);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> plugin === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">      <span class="comment">//如果plugin是一个函数，则直接通过apply去调用</span></span><br><span class="line">      plugin.<span class="title function_">apply</span>(<span class="literal">null</span>, args);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//将插件存储到installedPlugins数组中。</span></span><br><span class="line">    installedPlugins.<span class="title function_">push</span>(plugin);</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="2、install-方法分析"><a href="#2、install-方法分析" class="headerlink" title="2、install 方法分析"></a>2、install 方法分析</h2><p>我们先来看一下<code>vue-router</code>的目录结构</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%20Router/vueRouter/vuerouter%E7%9B%AE%E5%BD%95.png" alt="image-20200829210549006"></p>
<p>我们先来核心的文件。</p>
<p><code>components</code>目录下面，有两个文件。分别为<code>link.js</code>和<code>view.js</code>文件。</p>
<p><code>link.js</code>文件创建<code>RouterLink</code>组件</p>
<p><code>view.js</code>文件创建<code>RouterView</code>组件。</p>
<p><code>history</code>目录下的文件是记录路由的历史记录（<code>hash.js</code>文件是关于<code>hash</code>模式，<code>html5.js</code>关于<code>html5</code>的方式，<code>base.js</code>公共的内容，<code>abstract.js</code>是在服务端渲染中实现的路由历史记录）。</p>
<p><code>index.js</code>文件是用来创建<code>VueRouter</code></p>
<p><code>install.js</code>文件是关于<code>install</code>方法</p>
<p>我们自己模拟的<code>VueRouter</code>也实现上面的目录结构。</p>
<p>下面先来在<code>index.js</code>文件中实现基本代码。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">VueRouter</span> &#123;</span><br><span class="line">  <span class="comment">//在创建VueRouter对象的时候，会传递选项</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="comment">//获取routes选项，该选项中定义路由规则</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_options</span> = options.<span class="property">routes</span> || [];</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 注册路由变化的事件。该方法的参数是一个Vue实例，后期完善</span></span><br><span class="line">  <span class="title function_">init</span>(<span class="params">Vue</span>) &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面实现<code>install.js</code>基本代码（通过查看源代码来实现）</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">let</span> _Vue = <span class="literal">null</span>; <span class="comment">//将其导出，在其它文件中也可以使用Vue实例，而不需要单独的引入Vue的js文件</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">install</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">  <span class="comment">//获取Vue构造函数</span></span><br><span class="line">  _Vue = <span class="title class_">Vue</span>;</span><br><span class="line">  _Vue.<span class="title function_">mixin</span>(&#123;</span><br><span class="line">    <span class="comment">//通过混入以后，所有的Vue实例中都会有beforeCreate方法</span></span><br><span class="line">    <span class="title function_">beforeCreate</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">//判断是否为Vue的实例，如果条件成立为Vue的实例，否则为其它对应的组件（因为在创建Vue实例的时候会传递选项）</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>) &#123;</span><br><span class="line">        <span class="comment">//通过查看源码发现，Vue的实例会挂在到当前的私有属性_routerRoot属性上</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_routerRoot</span> = <span class="variable language_">this</span>;</span><br><span class="line"></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_router</span> = <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>;</span><br><span class="line">        <span class="comment">//调用index.js文件中定义的init方法</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="title function_">init</span>(<span class="variable language_">this</span>);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_routerRoot</span> = <span class="variable language_">this</span>.<span class="property">$parent</span> &amp;&amp; <span class="variable language_">this</span>.<span class="property">$parent</span>.<span class="property">_routerRoot</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3、组件创建测试"><a href="#3、组件创建测试" class="headerlink" title="3、组件创建测试"></a>3、组件创建测试</h2><p>下面需要将<code>install</code>方法挂载到<code>VueRouter</code>上。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> install <span class="keyword">from</span> <span class="string">&quot;./install&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">VueRouter</span> &#123;</span><br><span class="line">  <span class="comment">//在创建VueRouter对象的时候，会传递选项</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="comment">//获取routes选项，该选项中定义路由规则</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_routes</span> = options.<span class="property">routes</span> || [];</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 注册路由变化的事件。</span></span><br><span class="line">  <span class="title function_">init</span>(<span class="params">Vue</span>) &#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将install方法挂载到VueRouter上</span></span><br><span class="line"><span class="title class_">VueRouter</span>.<span class="property">install</span> = install;</span><br></pre></td></tr></table></figure>

<p>下面，我们可以简单实现一下<code>Router-link</code>组件与<code>Router-view</code>组件，来做一个简单的测试。<strong>（接下来讲解如下内容）</strong></p>
<p><code>components</code>目录下的<code>view.js</code>文件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(<span class="string">&quot;div&quot;</span>, <span class="string">&quot;router-view&quot;</span>);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>以上是<code>Router-View</code>组件的基本功能，后面在继续完善。</p>
<p><code>link.js</code>文件的实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">props</span>: &#123;</span><br><span class="line">    <span class="attr">to</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">String</span>,</span><br><span class="line">      <span class="attr">required</span>: <span class="literal">true</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="comment">//通过插槽获取`a`标签内的文本。</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(<span class="string">&quot;a&quot;</span>, &#123; <span class="attr">domProps</span>: &#123; <span class="attr">href</span>: <span class="string">&quot;#&quot;</span> + <span class="variable language_">this</span>.<span class="property">to</span> &#125; &#125;, [<span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span>]);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在<code>install.js</code>文件中，导入上面的组件进行测试。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">View</span> <span class="keyword">from</span> <span class="string">&quot;./components/view&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Link</span> <span class="keyword">from</span> <span class="string">&quot;./components/link&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">let</span> _Vue = <span class="literal">null</span>; <span class="comment">//将其导出，在其它文件中也可以使用Vue实例，而不需要单独的引入Vue的js文件</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">install</span>(<span class="params">Vue</span>) &#123;</span><br><span class="line">  <span class="comment">//获取Vue构造函数</span></span><br><span class="line">  _Vue = <span class="title class_">Vue</span>;</span><br><span class="line">  _Vue.<span class="title function_">mixin</span>(&#123;</span><br><span class="line">    <span class="comment">//通过混入以后，所有的Vue实例中都会有beforeCreate方法</span></span><br><span class="line">    <span class="title function_">beforeCreate</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">//判断是否为Vue的实例，如果条件成立为Vue的实例，否则为其它对应的组件（因为在创建Vue实例的时候会传递选项）</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>) &#123;</span><br><span class="line">        <span class="comment">//通过查看源码发现，Vue的实例会挂在到当前的私有属性_routerRoot属性上</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_routerRoot</span> = <span class="variable language_">this</span>;</span><br><span class="line"></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_router</span> = <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>;</span><br><span class="line">        <span class="comment">//调用index.js文件中定义的init方法</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="title function_">init</span>(<span class="variable language_">this</span>);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_routerRoot</span> = <span class="variable language_">this</span>.<span class="property">$parent</span> &amp;&amp; <span class="variable language_">this</span>.<span class="property">$parent</span>.<span class="property">_routerRoot</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="comment">//完成组件的注册</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;RouterView&quot;</span>, <span class="title class_">View</span>);</span><br><span class="line">  <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;RouterLink&quot;</span>, <span class="title class_">Link</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，导入组件，并且完成组件的注册。</p>
<p>下面，我们测试一下。</p>
<p>在<code>src</code>目录下，在<code>router.js</code>文件中导入自己定义的<code>VueRouter</code>.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">import Router from &quot;./my-vue-router&quot;;</span><br></pre></td></tr></table></figure>

<h2 id="4、解析路由规则"><a href="#4、解析路由规则" class="headerlink" title="4、解析路由规则"></a>4、解析路由规则</h2><p>下面，我们要做的就是对所有的路由规则进行解析，将其解析到一个数组中。方便根据地址找到对应的组件。</p>
<p>在源码的<code>index.js</code>文件中，创建了<code>VueRouter</code>类，对应的构造方法中，有如下代码：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">this.matcher = createMatcher(options.routes || [], this)</span><br></pre></td></tr></table></figure>

<p><code>createMatcher</code>方法是在<code>create-matcher.js</code>文件中创建的。</p>
<p>该方法返回的<code>matcher</code> 就是一个匹配器，其中有两个成员，<code>match</code>,另外一个是<code>addRoutes</code></p>
<p><code>match</code>:根据路由地址匹配相应的路由规则对象。</p>
<p><code>addRoutes</code>动态添加路由</p>
<p>首先在我们自己的<code>index.js</code>文件中添加如下的代码：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> install <span class="keyword">from</span> <span class="string">&quot;./install&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> createMatcher <span class="keyword">from</span> <span class="string">&quot;./create-matcher&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">VueRouter</span> &#123;</span><br><span class="line">  <span class="comment">//在创建VueRouter对象的时候，会传递选项</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="comment">//获取routes选项，该选项中定义路由规则</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_routes</span> = options.<span class="property">routes</span> || [];</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">matcher</span> = <span class="title function_">createMatcher</span>(<span class="variable language_">this</span>.<span class="property">_routes</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 注册路由变化的事件。</span></span><br><span class="line">  <span class="title function_">init</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">  <span class="comment">//init(Vue)&#123;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将install方法挂载到VueRouter上</span></span><br><span class="line"><span class="title class_">VueRouter</span>.<span class="property">install</span> = install;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，导入了<code>createMatcher</code>方法。</p>
<p>并且在调用该方法的时候传递了路由规则。</p>
<p><code>create-matcher.js</code> 文件的代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> createRouteMap <span class="keyword">from</span> <span class="string">&quot;./create-route-map&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">createMatcher</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123; pathList, pathMap &#125; = <span class="title function_">createRouteMap</span>(routes);</span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">match</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">addRoutes</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">    <span class="title function_">createRouteMap</span>(routes, pathList, pathMap);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    match,</span><br><span class="line">    addRoutes,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面，我们需要在<code>create-route-map.js</code> 文件中实现<code>createRouteMap</code>这个方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">createRouteMap</span>(<span class="params">routes, oldPathList, oldPathMap</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> pathList = oldPathList || [];</span><br><span class="line">  <span class="keyword">const</span> pathMap = oldPathMap || &#123;&#125;;</span><br><span class="line">  <span class="comment">//遍历所有的路由规则，进行解析。同时还要考虑children的形式，</span></span><br><span class="line">  <span class="comment">//所以这里需要使用递归的方式。</span></span><br><span class="line">  routes.<span class="title function_">forEach</span>(<span class="function">(<span class="params">route</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">addRouteRecord</span>(route, pathList, pathMap);</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    pathList,</span><br><span class="line">    pathMap,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">addRouteRecord</span>(<span class="params">route, pathList, pathMap, parentRecord</span>) &#123;</span><br><span class="line">  <span class="comment">//从路由规则中获取path。</span></span><br><span class="line">  <span class="keyword">const</span> path = parentRecord ? <span class="string">`<span class="subst">$&#123;parentRecord.path&#125;</span>/<span class="subst">$&#123;route.path&#125;</span>`</span> : route.<span class="property">path</span>;</span><br><span class="line">  <span class="comment">//构建记录</span></span><br><span class="line">  <span class="keyword">const</span> record = &#123;</span><br><span class="line">    path,</span><br><span class="line">    <span class="attr">component</span>: route.<span class="property">component</span>,</span><br><span class="line">    <span class="attr">parent</span>: parentRecord, <span class="comment">//如果是子路由的话，记录子路由对应的父record对象（该对象中有path,component）,相当于记录了父子关系</span></span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="comment">//如果已经有了path,相同的path直接跳过</span></span><br><span class="line">  <span class="keyword">if</span> (!pathMap[path]) &#123;</span><br><span class="line">    pathList.<span class="title function_">push</span>(path);</span><br><span class="line">    pathMap[path] = record;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//判断route中是否有子路由</span></span><br><span class="line">  <span class="keyword">if</span> (route.<span class="property">children</span>) &#123;</span><br><span class="line">    <span class="comment">//遍历子路由，把子路由添加到pathList与pathMap中。</span></span><br><span class="line">    route.<span class="property">children</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">childRoute</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">addRouteRecord</span>(childRoute, pathList, pathMap, record);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面测试一下上面的代码。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> createRouteMap <span class="keyword">from</span> <span class="string">&quot;./create-route-map&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">createMatcher</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123; pathList, pathMap &#125; = <span class="title function_">createRouteMap</span>(routes);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;pathList==&quot;</span>, pathList);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;pathMap==&quot;</span>, pathMap);</span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">match</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">addRoutes</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">    <span class="title function_">createRouteMap</span>(routes, pathList, pathMap);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    match,</span><br><span class="line">    addRoutes,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们打印了<code>pathList</code>与<code>pathMap</code>.</p>
<p>当然，现在在我们所定义的路由规则中，还没有添加<code>children</code>,构建相应的子路由。下面重新修改一下。</p>
<p>在项目根目录下的<code>router.js</code>文件中，添加对应的子路由规则。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="comment">// import Router from &quot;vue-router&quot;;</span></span><br><span class="line"><span class="comment">// import Router from &quot;./vuerouter&quot;;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Router</span> <span class="keyword">from</span> <span class="string">&quot;./my-vue-router&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Login</span> <span class="keyword">from</span> <span class="string">&quot;./components/Login.vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Home</span> <span class="keyword">from</span> <span class="string">&quot;./components/Home.vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">About</span> <span class="keyword">from</span> <span class="string">&quot;./components/About.vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Users</span> <span class="keyword">from</span> <span class="string">&quot;./components/Users&quot;</span>;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Router</span>);</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Router</span>(&#123;</span><br><span class="line">  <span class="comment">// model: &quot;history&quot;,</span></span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>, <span class="attr">component</span>: <span class="title class_">Home</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">&quot;/login&quot;</span>, <span class="attr">component</span>: <span class="title class_">Login</span> &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&quot;/about&quot;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="title class_">About</span>,</span><br><span class="line">      <span class="attr">children</span>: [&#123; <span class="attr">path</span>: <span class="string">&quot;users&quot;</span>, <span class="attr">component</span>: <span class="title class_">Users</span> &#125;],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>这时候可以查看对应的输出结果。</p>
<h2 id="5、match函数实现"><a href="#5、match函数实现" class="headerlink" title="5、match函数实现"></a>5、<code>match</code>函数实现</h2><p>在<code>create-matcher.js</code>文件中，我们实现了<code>createRouteMap</code>方法，同时还需要实现<code>match</code>方法。</p>
<p><code>match</code>方法的作用就是根据路由地址，匹配一个路由对象。其实就是从<code>pathMap</code>中根据路由地址，找出对应的路由记录。路由记录中记录了组件信息，找到以后就可以完成组件的创建，渲染了。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">match</span>(<span class="params">path</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> record = pathMap[path];</span><br><span class="line">  <span class="keyword">if</span> (record) &#123;</span><br><span class="line">    <span class="comment">//根据路由地址，创建route路由规则对象</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">createRoute</span>(record, path);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">createRoute</span>(<span class="literal">null</span>, path);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们调用<code>match</code>方法的时候，会传递过来一个路径，我们根据这个路径可以从<code>pathMap</code>中找到对应的路由记录信息(这块在上一小节已经创建完毕)，如果找到了，我们还需要做进一步的处理，为什么呢？因为，我们传递过来的路径有可能是子路径，这时不光要获取到对应的子路由信息，我们还需要去查找对应的父路由的信息。所以这里需要进一步的处理，关于这块的处理封装到了<code>createRoute</code>这个方法中，而该方法在其它位置还需要，所以我们定义到<code>util</code>这个目录下<code>import createRoute from &quot;./util/route&quot;;</code>。</p>
<p><code>create-matcher.js</code>文件完整代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> createRouteMap <span class="keyword">from</span> <span class="string">&quot;./create-route-map&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> createRoute <span class="keyword">from</span> <span class="string">&quot;./util/route&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">createMatcher</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123; pathList, pathMap &#125; = <span class="title function_">createRouteMap</span>(routes);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;pathList==&quot;</span>, pathList);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;pathMap==&quot;</span>, pathMap);</span><br><span class="line">  <span class="comment">//实现match方法</span></span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">match</span>(<span class="params">path</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> record = pathMap[path];</span><br><span class="line">    <span class="keyword">if</span> (record) &#123;</span><br><span class="line">      <span class="comment">//根据路由地址，创建route路由规则对象</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">createRoute</span>(record, path);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">createRoute</span>(<span class="literal">null</span>, path);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">function</span> <span class="title function_">addRoutes</span>(<span class="params">routes</span>) &#123;</span><br><span class="line">    <span class="title function_">createRouteMap</span>(routes, pathList, pathMap);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    match,</span><br><span class="line">    addRoutes,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面我们需要在<code>my-vue-router</code>目录下面在创建一个<code>util</code>目录，在该目录下面创建<code>route.js</code>文件，该文件实现的代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">createRoute</span>(<span class="params">record, path</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> matched = [];</span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span> (record) &#123;</span><br><span class="line">    matched.<span class="title function_">unshift</span>(record);</span><br><span class="line">    record = record.<span class="property">parent</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    path,</span><br><span class="line">    matched,</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>总结：<code>match</code>这个方法的作用就是根据路径，创建出路由规则对象，而所谓的路由规则对象其实就是包含了路径以及对应的路由记录的信息(这里有可能包含了父路由以及子路由记录，这块内容存储到一个数组中)。</p>
<p>以后，我们就可以根据路径直接获取到包含了整个路由记录的这个数组，从而可以将对应的组件全部创建出来。</p>
<h2 id="6、历史记录处理"><a href="#6、历史记录处理" class="headerlink" title="6、历史记录处理"></a>6、历史记录处理</h2><p>关于路由有三种模式：<code>hash</code>模式，<code>html5</code>模式，<code>abstract</code>模式（该模式与服务端渲染有关）</p>
<p>在这里我们实现<code>hash</code>模式的历史记录管理，不管是哪种模式，都有相同的内容，这里我们相同的内容定义到</p>
<p>父类中。</p>
<p>在该父类中主要有如下内容：</p>
<p><code>router</code>属性：路由对象（<code>ViewRouter</code>）</p>
<p><code>current</code>属性，记录当前路径对应的路由规则对象<code>&#123;path:&#39;/&#39;,matched:[]&#125;</code>,关于该对象，我们在前面已经处理完了。也就是在<code>createRoute</code>方法中返回的内容。</p>
<p><code>transitionTo()</code></p>
<p>跳转到指定的路径，根据当前路径获取匹配的路由规则对象<code>route</code>，然后更新视图。</p>
<p>在<code>my-vue-router</code>目录下的，<code>history</code>目录下的<code>base.js</code>文件，编写如下的代码：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> createRoute <span class="keyword">from</span> <span class="string">&quot;../util/route&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">History</span> &#123;</span><br><span class="line">  <span class="comment">// router路由对象ViewRouter</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">router</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">router</span> = router;</span><br><span class="line"></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">current</span> = <span class="title function_">createRoute</span>(<span class="literal">null</span>, <span class="string">&quot;/&quot;</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">transitionTo</span>(<span class="params">path, onComplete</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">current</span> = <span class="variable language_">this</span>.<span class="property">router</span>.<span class="property">matcher</span>.<span class="title function_">match</span>(path);</span><br><span class="line">    <span class="comment">//该回调函数在调用transitionTo方法的时候，会传递过来。</span></span><br><span class="line">    onComplete &amp;&amp; <span class="title function_">onComplete</span>();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>父类已经实现了，下面实现对应的子类。也就是<code>HashHistory</code></p>
<p><code>HashHistory</code>继承<code>History</code>, 同时要确保首次访问的地址为<code>#/</code>.</p>
<p>在<code>History</code>中还需要定义两个方法，第一个方法为：<code>getCurrentLocation( )</code> 获取当前的路由地址(<code>#</code> 后面的部分)</p>
<p><code>setUpListener( )</code>方法监听路由地址改变的事件（<code>hashchange</code>）。</p>
<p>在<code>history</code>目录下的<code>hash.js</code>文件中的代码实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">History</span> <span class="keyword">from</span> <span class="string">&quot;./base&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">HashHistory</span> <span class="keyword">extends</span> <span class="title class_ inherited__">History</span> &#123;</span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">router</span>) &#123;</span><br><span class="line">    <span class="comment">//将路由对象传递给父类的构造函数</span></span><br><span class="line">    <span class="variable language_">super</span>(router);</span><br><span class="line">    <span class="comment">//确保 首次 访问地址加上 #/  （//由于没有添加this,为普通方法）</span></span><br><span class="line">    <span class="title function_">ensureSlash</span>();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 获取当前的路由地址 （# 后面的部分）所以这里需要去除#</span></span><br><span class="line">  <span class="title function_">getCurrentLocation</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">hash</span>.<span class="title function_">slice</span>(<span class="number">1</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 监听hashchange事件</span></span><br><span class="line">  <span class="comment">//也就是监听路由地址的变化</span></span><br><span class="line">  <span class="title function_">setUpListener</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;hashchange&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">//当路由地址发生变化后，跳转到新的路由地址。</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="title function_">transitionTo</span>(<span class="variable language_">this</span>.<span class="title function_">getCurrentLocation</span>());</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">ensureSlash</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">//判断当前是否有hash</span></span><br><span class="line">  <span class="comment">// 如果单击的是链接，肯定会有hash</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">hash</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">hash</span> = <span class="string">&quot;/&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="7、Init方法实现"><a href="#7、Init方法实现" class="headerlink" title="7、Init方法实现"></a>7、<code>Init</code>方法实现</h2><p>我们知道当创建<code>VueRouter</code> 的时候，需要可以传递<code>mode</code>，来指定路由的形式，例如是<code>hash</code>模式还是<code>html5</code>模式等。</p>
<p>所以这里需要根据指定的<code>mode</code>的模式，来选择<code>history</code>目录中中不同<code>js</code>来处理。</p>
<p>所以在<code>my-vue-router</code>目录中的<code>index.js</code>文件中，做如下的修改：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> install <span class="keyword">from</span> <span class="string">&quot;./install&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> createMatcher <span class="keyword">from</span> <span class="string">&quot;./create-matcher&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">HashHistory</span> <span class="keyword">from</span> <span class="string">&quot;./history/hash&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">HTML5History</span> <span class="keyword">from</span> <span class="string">&quot;./history/html5&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">VueRouter</span> &#123;</span><br><span class="line">  <span class="comment">//在创建VueRouter对象的时候，会传递选项</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="comment">//获取routes选项，该选项中定义路由规则</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_routes</span> = options.<span class="property">routes</span> || [];</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">matcher</span> = <span class="title function_">createMatcher</span>(<span class="variable language_">this</span>.<span class="property">_routes</span>);</span><br><span class="line">    <span class="comment">//获取传递过来的选项中的mode,mode中决定了用户设置的路由的形式。</span></span><br><span class="line">    <span class="comment">//这里给VueRouter添加了mode属性</span></span><br><span class="line">    <span class="keyword">const</span> mode = (<span class="variable language_">this</span>.<span class="property">mode</span> = options.<span class="property">mode</span> || <span class="string">&quot;hash&quot;</span>);</span><br><span class="line">    <span class="keyword">switch</span> (mode) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&quot;hash&quot;</span>:</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">history</span> = <span class="keyword">new</span> <span class="title class_">HashHistory</span>(<span class="variable language_">this</span>);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&quot;history&quot;</span>:</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">history</span> = <span class="keyword">new</span> <span class="title class_">HTML5History</span>(<span class="variable language_">this</span>);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      <span class="attr">default</span>:</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&quot;mode error&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 注册路由变化的事件。</span></span><br><span class="line">  <span class="title function_">init</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">  <span class="comment">//init(Vue)&#123;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将install方法挂载到VueRouter上</span></span><br><span class="line"><span class="title class_">VueRouter</span>.<span class="property">install</span> = install;</span><br></pre></td></tr></table></figure>

<p>首先导入<code>HashHistory</code> 与<code>HTML5History</code>.</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">HashHistory</span> <span class="keyword">from</span> <span class="string">&quot;./history/hash&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">HTML5History</span> <span class="keyword">from</span> <span class="string">&quot;./history/html5&quot;</span>;</span><br></pre></td></tr></table></figure>

<p>下面获取选项中的<code>mode</code>,如果在创建<code>VueRouter</code>对象的时候，没有指定<code>mode</code>,那么默认的值为<code>hash</code>.</p>
<p>下面就对获取到的<code>mode</code>进行判断，根据<code>mode</code>的不同的值，创建不同的<code>history</code>的实例。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//获取传递过来的选项中的mode,mode中决定了用户设置的路由的形式。</span></span><br><span class="line"><span class="comment">//这里给VueRouter添加了mode属性</span></span><br><span class="line"><span class="keyword">const</span> mode = (<span class="variable language_">this</span>.<span class="property">mode</span> = options.<span class="property">mode</span> || <span class="string">&quot;hash&quot;</span>);</span><br><span class="line"><span class="keyword">switch</span> (mode) &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&quot;hash&quot;</span>:</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">history</span> = <span class="keyword">new</span> <span class="title class_">HashHistory</span>(<span class="variable language_">this</span>);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&quot;history&quot;</span>:</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">history</span> = <span class="keyword">new</span> <span class="title class_">HTML5History</span>(<span class="variable language_">this</span>);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="attr">default</span>:</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&quot;mode error&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>同时<code>html5.js</code>文件，添加了基本的代码</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">History</span> <span class="keyword">from</span> <span class="string">&quot;./base&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">HTML5History</span> <span class="keyword">extends</span> <span class="title class_ inherited__">History</span> &#123;&#125;</span><br></pre></td></tr></table></figure>

<p>关于<code>Html5</code>的形式这里不在实现了。</p>
<p>下面完善一下<code>init</code>方法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 注册路由变化的事件。</span></span><br><span class="line"> <span class="title function_">init</span>(<span class="params"></span>) &#123;&#125;</span><br></pre></td></tr></table></figure>

<p>具体的实现代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 注册路由变化的事件(初始化事件监听器，监听路由地址的变化)。</span></span><br><span class="line"><span class="title function_">init</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> history = <span class="variable language_">this</span>.<span class="property">history</span>;</span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">setUpListener</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    history.<span class="title function_">setUpListener</span>();</span><br><span class="line">  &#125;;</span><br><span class="line">  history.<span class="title function_">transitionTo</span>(</span><br><span class="line">    history.<span class="title function_">getCurrentLocation</span>(),</span><br><span class="line">    <span class="comment">//如果直接history.setUpListener</span></span><br><span class="line">    <span class="comment">// 这样的话setUpListener里面的this会有问题。</span></span><br><span class="line">    setUpListener</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在这里，调用了<code>transitionTo</code>方法的原因是，在<code>hash.js</code>文件中的<code>ensureSlash</code>方法中，完成了一次地址的修改，所以这里需要跳转一次。</p>
<p>同时完成了<code>hashchange</code>事件的绑定（路由变化的事件）。</p>
<p>下面可以进行测试一下，在<code>base.js</code>文件中的<code>transitionTo</code>方法中，打印出<code>current</code>属性的值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"> <span class="title function_">transitionTo</span>(<span class="params">path, onComplete</span>) &#123;</span><br><span class="line">   <span class="variable language_">this</span>.<span class="property">current</span> = <span class="variable language_">this</span>.<span class="property">router</span>.<span class="property">matcher</span>.<span class="title function_">match</span>(path);</span><br><span class="line">   <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;current===&quot;</span>, <span class="variable language_">this</span>.<span class="property">current</span>);</span><br><span class="line"><span class="comment">//该回调函数在调用transitionTo方法的时候，会传递过来。</span></span><br><span class="line">   onComplete &amp;&amp; <span class="title function_">onComplete</span>();</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>下面，在浏览器的地址栏中输入了不同的<code>URL</code>地址后，在控制台上呈现出了不同的路由规则对象，也就是路由记录信息。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">http://localhost:8080/#/about/users</span><br></pre></td></tr></table></figure>

<p>输入以上地址，该地址为子路由的地址，最终也输出了对应的父路由的记录信息。</p>
<p>后期就可以获取具体的组件来进行渲染。</p>
<h2 id="8、设置响应式的-route"><a href="#8、设置响应式的-route" class="headerlink" title="8、设置响应式的_route"></a>8、设置响应式的_route</h2><p>下面我们要做的就是渲染组件。</p>
<p>这里我们先创建一个与路由有关的响应式属性，当路由地址发生变化了，对应的该属性也要发生变化，从而完成页面的重新渲染。</p>
<p>在<code>install.js</code>文件中添加如下的代码：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="property">util</span>.<span class="title function_">defineReactive</span>(<span class="variable language_">this</span>, <span class="string">&quot;_route&quot;</span>, <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="property">history</span>.<span class="property">current</span>);</span><br></pre></td></tr></table></figure>

<p>以上完成了响应式属性的创建，但是要注意的是<code>defineReactive</code>方法为<code>Vue</code>的内部方法，不建议平时通过该方法来创建响应式对象。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">beforeCreate</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">//判断是否为Vue的实例，如果条件成立为Vue的实例，否则为其它对应的组件（因为在创建Vue实例的时候会传递选项）</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>) &#123;</span><br><span class="line">      <span class="comment">//通过查看源码发现，Vue的实例会挂在到当前的私有属性_routerRoot属性上</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">_routerRoot</span> = <span class="variable language_">this</span>;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">_router</span> = <span class="variable language_">this</span>.<span class="property">$options</span>.<span class="property">router</span>;</span><br><span class="line">      <span class="comment">//调用index.js文件中定义的init方法</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="title function_">init</span>(<span class="variable language_">this</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">      <span class="comment">//在Vue的实例上创建一个响应式的属性`_route`.</span></span><br><span class="line">      <span class="title class_">Vue</span>.<span class="property">util</span>.<span class="title function_">defineReactive</span>(<span class="variable language_">this</span>, <span class="string">&quot;_route&quot;</span>, <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="property">history</span>.<span class="property">current</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>下面要考虑的就是当路由地址发生了变化后，需要修改<code>_route</code>属性的值。</p>
<p>在哪完成<code>_route</code>属性值的修改呢？</p>
<p>在<code>base.js</code>文件中，因为在该文件中定义了<code>transitionTo</code>方法，而该方法就是用来完成地址的跳转，同时完成组件的渲染。</p>
<p><code>base.js</code>文件修改后的代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> createRoute <span class="keyword">from</span> <span class="string">&quot;../util/route&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">History</span> &#123;</span><br><span class="line">  <span class="comment">// router路由对象ViewRouter</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">router</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">router</span> = router;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">current</span> = <span class="title function_">createRoute</span>(<span class="literal">null</span>, <span class="string">&quot;/&quot;</span>);</span><br><span class="line">    <span class="comment">//这个回调函数是在hashhistory中赋值，作用是更改vue实例上的_route，_route的值发生变化，视图会进行刷新操作</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">cb</span> = <span class="literal">null</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//给cb赋值</span></span><br><span class="line">  <span class="title function_">listen</span>(<span class="params">cb</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">cb</span> = cb;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">transitionTo</span>(<span class="params">path, onComplete</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">current</span> = <span class="variable language_">this</span>.<span class="property">router</span>.<span class="property">matcher</span>.<span class="title function_">match</span>(path);</span><br><span class="line">    <span class="comment">// 调用cb</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">cb</span> &amp;&amp; <span class="variable language_">this</span>.<span class="title function_">cb</span>(<span class="variable language_">this</span>.<span class="property">current</span>);</span><br><span class="line">    <span class="comment">// console.log(&quot;current===&quot;, this.current);</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//该回调函数在调用transitionTo方法的时候，会传递过来。</span></span><br><span class="line">    onComplete &amp;&amp; <span class="title function_">onComplete</span>();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在<code>History</code>中的构造方法中初始化<code>cb</code>函数。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">this.cb = null;</span><br></pre></td></tr></table></figure>

<p>定义<code>listen</code>方法给<code>cb</code>函数赋值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//给cb赋值</span></span><br><span class="line">  <span class="title function_">listen</span>(<span class="params">cb</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">cb</span> = cb;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>在<code>transitionTo</code> 方法中调用<code>cb</code>函数，同时传递获取到的当前的路由规则对象也就是路由记录信息。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="variable language_">this</span>.<span class="property">cb</span> &amp;&amp; <span class="variable language_">this</span>.<span class="title function_">cb</span>(<span class="variable language_">this</span>.<span class="property">current</span>);</span><br></pre></td></tr></table></figure>

<p>在什么地方调用<code>listen</code>方法呢？</p>
<p>在<code>index.js</code>文件中的<code>init</code>方法中完成<code>listen</code>方法的调用。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 注册路由变化的事件(初始化事件监听器，监听路由地址的变化)。</span></span><br><span class="line">  <span class="title function_">init</span>(<span class="params">app</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> history = <span class="variable language_">this</span>.<span class="property">history</span>;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">setUpListener</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">      history.<span class="title function_">setUpListener</span>();</span><br><span class="line">    &#125;;</span><br><span class="line">    history.<span class="title function_">transitionTo</span>(</span><br><span class="line">      history.<span class="title function_">getCurrentLocation</span>(),</span><br><span class="line">      <span class="comment">//如果直接history.setUpListener</span></span><br><span class="line">      <span class="comment">// 这样的话setUpListener里面的this会有问题。</span></span><br><span class="line">      setUpListener</span><br><span class="line">    );</span><br><span class="line">    <span class="comment">//调用父类的中的listen方法</span></span><br><span class="line">    history.<span class="title function_">listen</span>(<span class="function">(<span class="params">route</span>) =&gt;</span> &#123;</span><br><span class="line">      app.<span class="property">_route</span> = route;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中调用了父类中的<code>listen</code>方法，然后将箭头函数传递到了<code>listen</code>中。</p>
<p>这时候，在<code>transitionTo</code>方法中调用<code>cb</code>，也就是调用箭头函数，这时传递过来的参数<code>route</code>,为当前更改后的路由规则信息，交给了<code>app</code>中的<code>_route</code>属性。</p>
<p><code>app</code>这个参数其实就是<code>Vue</code>的实例，因为在<code>install.js</code>文件中调用了<code>init</code>方法，并且传递的就是<code>Vue</code>的实例。</p>
<p>这样就完成了对<code>Vue</code>实例上的响应式属性<code>_route</code>值的修改，从而会更新组件。</p>
<h2 id="9、-route-router创建"><a href="#9、-route-router创建" class="headerlink" title="9、$route/$router创建"></a>9、<code>$route/$router</code>创建</h2><p>创建<code>$route</code>与<code>$router</code>的目的是能够在所有的<code>Vue</code>实例(组件)中，可以获取到。</p>
<p><code>$route</code>是路由规则对象，包含了<code>path</code>,<code>component</code>等内容</p>
<p><code>$router</code>为路由对象（<code>ViewRouter</code>对象）。</p>
<p>通过查看源码(<code>install.js</code>)可以发现，其实就是将<code>$router</code> 与<code>$route</code>挂载到了<code>Vue</code>的原型上。</p>
<p>所以可以直接将源码内容复制过来就可以了。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(<span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>, <span class="string">&quot;$router&quot;</span>, &#123;</span><br><span class="line">  <span class="title function_">get</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_routerRoot</span>.<span class="property">_router</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(<span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>, <span class="string">&quot;$route&quot;</span>, &#123;</span><br><span class="line">  <span class="title function_">get</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_routerRoot</span>.<span class="property">_route</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>通过上面的代码，可以看到<code>$route</code>与<code>$router</code> 都是只读的，因为对应的值，在前面已经设置完毕，这里只是获取。</p>
<p><code>$router</code> 是通过<code>_routerRoot</code>来获取。</p>
<p><code>$route</code>是通过<code>_routerRoot._route</code>来获取。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="property">util</span>.<span class="title function_">defineReactive</span>(<span class="variable language_">this</span>, <span class="string">&quot;_route&quot;</span>, <span class="variable language_">this</span>.<span class="property">_router</span>.<span class="property">history</span>.<span class="property">current</span>);</span><br></pre></td></tr></table></figure>

<p>在<code>Vue</code>对象上创建了<code>_route</code>属性，该属性的值为路由规则内容</p>
<h2 id="10、Router-View创建"><a href="#10、Router-View创建" class="headerlink" title="10、Router-View创建"></a>10、<code>Router-View</code>创建</h2><p><code>router-view</code>就是一个占位符，会用具体的组件来替换该占位符。</p>
<p><code>router-view</code>的创建过程如下：</p>
<ul>
<li>获取当前组件的<code>$route</code>路由规则对象</li>
<li>找到路由规则对象里面的<code>matched</code> 匹配的<code>record</code>(里面有 component)</li>
<li>如果是<code>/about</code> ,<code>matched</code>匹配到一个<code>record</code>，直接渲染对应的组件</li>
<li>如果是<code>/about/users</code>,<code>matched</code> 匹配到两个<code>record</code>（第一个是父组件，第二个是子组件）</li>
</ul>
<p><code>my-vue-router/components</code>目录下的<code>view.js</code>代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="comment">//获取当前匹配的路由规则对象</span></span><br><span class="line">    <span class="keyword">const</span> route = <span class="variable language_">this</span>.<span class="property">$route</span>;</span><br><span class="line">    <span class="comment">//获取路由记录对象.只有一个内容，所以获取的是`matched`中的第一项。</span></span><br><span class="line">    <span class="keyword">const</span> record = route.<span class="property">matched</span>[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">if</span> (!record) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">h</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取记录中对应的组件</span></span><br><span class="line">    <span class="keyword">const</span> component = record.<span class="property">component</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(component);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>以上的代码处理的是没有子路由的情况。</p>
<p>下面，看一下子路由情况的处理。</p>
<p>当然在编写子路由的处理代码之前，我们先把案例中的路由完善一下。</p>
<p>在<code>src</code>目录下的<code>App.vue</code>这个组件中，添加一个“关于”的链接。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">    &lt;div id=&quot;nav&quot;&gt;</span><br><span class="line">      &lt;router-link to=&quot;/&quot;&gt;Home&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link to=&quot;/login&quot;&gt;Login&lt;/router-link&gt;</span><br><span class="line">      &lt;router-link to=&quot;/about&quot;&gt;About&lt;/router-link&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;&#125;;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>对应在<code>About</code> 这个组件中，完成子路由应用</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    关于组件</span><br><span class="line">    &lt;router-link to=&quot;/about/users&quot;&gt;用户&lt;/router-link&gt;</span><br><span class="line">    &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p>下面完善一下对子路由的处理。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="comment">//获取当前匹配的路由规则对象</span></span><br><span class="line">    <span class="keyword">const</span> route = <span class="variable language_">this</span>.<span class="property">$route</span>;</span><br><span class="line">    <span class="keyword">let</span> depth = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//记录当前组件为RouterView</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">routerView</span> = <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">let</span> parent = <span class="variable language_">this</span>.<span class="property">$parent</span>;</span><br><span class="line">    <span class="keyword">while</span> (parent) &#123;</span><br><span class="line">      <span class="keyword">if</span> (parent.<span class="property">routerView</span>) &#123;</span><br><span class="line">        depth++;</span><br><span class="line">      &#125;</span><br><span class="line">      parent = parent.<span class="property">$parent</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取路由记录对象.</span></span><br><span class="line">    <span class="comment">// 如果是子路由，例如：子路由/about/users</span></span><br><span class="line">    <span class="comment">//子路由是有两部分内容，matched[0]:是父组件内容，matched[1]是子组件内容</span></span><br><span class="line">    <span class="keyword">const</span> record = route.<span class="property">matched</span>[depth];</span><br><span class="line">    <span class="keyword">if</span> (!record) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">h</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取记录中对应的组件</span></span><br><span class="line">    <span class="keyword">const</span> component = record.<span class="property">component</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(component);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>假如，现在我们在浏览器的地址栏中输入了：<code>http://localhost:8080/#/about</code>地址，</p>
<p>是没有父组件，那么<code>depth</code>属性的值为 0，这时候获取的第一个组件然后进行渲染。</p>
<p>如果地址栏的内容为：<code>http://localhost:8080/#/about/users</code> 这时候有子组件。对应的获取对应的父组件内容，开始进行循环。</p>
<p>在循环的时候，做了一个判断，判断的条件就是当前的父组件必须为:<code>RouterView</code>组件（子组件中<code>router-view</code>与父组件中的<code>router-view</code>构成了父子关系），才让<code>depth</code>加 1，然后取出子组件进行渲染。</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">Justic</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2022/07/13/Vue/Vue%20Router/vueRouter/">http://example.com/2022/07/13/Vue/Vue Router/vueRouter/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://justicc.top/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">Justic</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Vue/">Vue</a></div><div class="post_share"><div class="social-share" data-image="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/wechat.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/alipay.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2022/07/13/JavaScript/JavaScript%20%E9%9D%A2%E8%AF%95%E7%B2%BE%E8%AE%B2/JavaScript%E9%9D%A2%E8%AF%95%E7%B2%BE%E8%AE%B2/"><img class="prev-cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">JavaScript 精讲</div></div></a></div><div class="next-post pull-right"><a href="/2022/07/13/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/"><img class="next-cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Vue 响应式原理</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/2022/07/13/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/" title="Vue 响应式原理"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-13</div><div class="title">Vue 响应式原理</div></div></a></div><div><a href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-10-20</div><div class="title">Vue 响应式解析</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%B8%B2%E6%9F%93/Vue%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B8%B2%E6%9F%93/" title="Vue 服务器渲染"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 服务器渲染</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/Vue%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/" title="Vue 源码解读"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 源码解读</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E8%99%9A%E6%8B%9Fdom/Vue%20%E8%99%9A%E6%8B%9Fdom/" title="Vue 虚拟DOM"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/k7/wallhaven-k7jmg6.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 虚拟DOM</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98/Vue%E9%9D%A2%E8%AF%95%E9%A2%98/" title="Vue 面试题"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 面试题</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div class="vcomment" id="vcomment"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://portrait.gitee.com/uploads/avatars/user/2982/8948190_JIAXInT_1624177607.png!avatar200" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Justic</div><div class="author-info__description">最是人间留不住 朱颜辞镜花辞树</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">25</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">3</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Vue-Router"><span class="toc-text">Vue Router</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80%E3%80%81Vue-Router-%E4%BB%8B%E7%BB%8D"><span class="toc-text">一、Vue Router 介绍</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E8%B7%AF%E7%94%B1%E7%AE%80%E4%BB%8B"><span class="toc-text">1、路由简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E5%AE%9E%E7%8E%B0%E7%AE%80%E6%98%93%E5%89%8D%E7%AB%AF%E8%B7%AF%E7%94%B1"><span class="toc-text">2、实现简易前端路由</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81vue-router%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">3、vue-router的基本使用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81%E8%B7%AF%E7%94%B1%E9%87%8D%E5%AE%9A%E5%90%91"><span class="toc-text">4、路由重定向</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81%E5%B5%8C%E5%A5%97%E8%B7%AF%E7%94%B1"><span class="toc-text">5、嵌套路由</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1%E5%8C%B9%E9%85%8D"><span class="toc-text">6、动态路由匹配</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#6-1-%E5%8A%A8%E6%80%81%E5%8C%B9%E9%85%8D%E8%B7%AF%E7%94%B1%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95"><span class="toc-text">6.1 动态匹配路由的基本用法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-2-%E8%B7%AF%E7%94%B1%E7%BB%84%E4%BB%B6%E4%BC%A0%E9%80%92%E5%8F%82%E6%95%B0"><span class="toc-text">6.2 路由组件传递参数</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81%E5%91%BD%E5%90%8D%E8%B7%AF%E7%94%B1"><span class="toc-text">7、命名路由</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81%E7%BC%96%E7%A8%8B%E5%BC%8F%E5%AF%BC%E8%88%AA"><span class="toc-text">8、编程式导航</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9%E3%80%81%E8%B7%AF%E7%94%B1%E6%A1%88%E4%BE%8B"><span class="toc-text">9、路由案例</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#9-1-%E6%8A%BD%E7%A6%BB%E5%B9%B6%E4%B8%94%E6%B8%B2%E6%9F%93App%E6%A0%B9%E7%BB%84%E4%BB%B6%E3%80%82"><span class="toc-text">9.1 抽离并且渲染App根组件。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-2-%E5%B0%86%E8%8F%9C%E5%8D%95%E6%94%B9%E9%80%A0%E4%B8%BA%E8%B7%AF%E7%94%B1%E8%BF%9E%E6%8E%A5"><span class="toc-text">9.2 将菜单改造为路由连接</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-3-%E5%88%9B%E5%BB%BA%E8%8F%9C%E5%8D%95%E5%AF%B9%E5%BA%94%E7%BB%84%E4%BB%B6"><span class="toc-text">9.3 创建菜单对应组件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-4-%E6%B7%BB%E5%8A%A0%E5%AD%90%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99%E5%B9%B6%E5%AE%9E%E7%8E%B0%E8%B7%AF%E7%94%B1%E9%87%8D%E5%AE%9A%E5%90%91"><span class="toc-text">9.4 添加子路由规则并实现路由重定向</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-5-%E6%B8%B2%E6%9F%93%E7%94%A8%E6%88%B7%E5%88%97%E8%A1%A8%E6%95%B0%E6%8D%AE"><span class="toc-text">9.5 渲染用户列表数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-6-%E8%B7%B3%E8%BD%AC%E5%88%B0%E8%AF%A6%E6%83%85%E9%A1%B5"><span class="toc-text">9.6 跳转到详情页</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10%E3%80%81%E8%B7%AF%E7%94%B1%E5%AE%88%E5%8D%AB"><span class="toc-text">10、路由守卫</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11%E3%80%81addRoutes-%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1%E6%B7%BB%E5%8A%A0"><span class="toc-text">11、addRoutes 动态路由添加</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12%E3%80%81%E8%B7%AF%E7%94%B1%E7%BB%84%E4%BB%B6%E7%BC%93%E5%AD%98"><span class="toc-text">12、路由组件缓存</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13%E3%80%81Hash-%E6%A8%A1%E5%BC%8F%E4%B8%8E-History-%E6%A8%A1%E5%BC%8F"><span class="toc-text">13、Hash 模式与 History 模式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#13-1-Hash-%E6%A8%A1%E5%BC%8F%E4%B8%8E-History-%E6%A8%A1%E5%BC%8F%E5%8C%BA%E5%88%AB"><span class="toc-text">13.1 Hash 模式与 History 模式区别</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-2-History%E6%A8%A1%E5%BC%8F%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-text">13.2 History模式的使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-3-%E5%9C%A8-Nginx-%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%AD%E9%85%8D%E7%BD%AEHistory%E6%A8%A1%E5%BC%8F"><span class="toc-text">13.3 在 Nginx 服务器中配置History模式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%8C%E3%80%81Vue-Router-%E5%8E%9F%E7%90%86"><span class="toc-text">二、Vue Router 原理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E5%88%86%E6%9E%90-Vue-Router"><span class="toc-text">1、分析 Vue Router</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81install-%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-text">2、install 方法实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E5%AE%9E%E7%8E%B0%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="toc-text">3、实现构造函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81createRouteMap-%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-text">4、createRouteMap 方法实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81initComponents-%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-text">5、initComponents 方法实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81render%E5%87%BD%E6%95%B0"><span class="toc-text">6、render函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81%E5%88%9B%E5%BB%BArouter-view%E7%BB%84%E4%BB%B6"><span class="toc-text">7、创建router-view组件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81initEvent%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-text">8、initEvent方法实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%89%E3%80%81VueRouter-%E6%A8%A1%E6%8B%9F%E5%AE%9E%E7%8E%B0%E4%B8%8E%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB"><span class="toc-text">三、VueRouter 模拟实现与源码解读</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81Vue-use-%E6%BA%90%E7%A0%81"><span class="toc-text">1、Vue.use( )源码</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81install-%E6%96%B9%E6%B3%95%E5%88%86%E6%9E%90"><span class="toc-text">2、install 方法分析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E7%BB%84%E4%BB%B6%E5%88%9B%E5%BB%BA%E6%B5%8B%E8%AF%95"><span class="toc-text">3、组件创建测试</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81%E8%A7%A3%E6%9E%90%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99"><span class="toc-text">4、解析路由规则</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81match%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0"><span class="toc-text">5、match函数实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E5%A4%84%E7%90%86"><span class="toc-text">6、历史记录处理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81Init%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-text">7、Init方法实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81%E8%AE%BE%E7%BD%AE%E5%93%8D%E5%BA%94%E5%BC%8F%E7%9A%84-route"><span class="toc-text">8、设置响应式的_route</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9%E3%80%81-route-router%E5%88%9B%E5%BB%BA"><span class="toc-text">9、$route&#x2F;$router创建</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10%E3%80%81Router-View%E5%88%9B%E5%BB%BA"><span class="toc-text">10、Router-View创建</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2022/11/09/JavaScript/ES6%E6%96%B0%E7%89%B9%E6%80%A7/index/" title="ES6新特性"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/m9/wallhaven-m9y289.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="ES6新特性"/></a><div class="content"><a class="title" href="/2022/11/09/JavaScript/ES6%E6%96%B0%E7%89%B9%E6%80%A7/index/" title="ES6新特性">ES6新特性</a><time datetime="2022-11-09T12:55:33.000Z" title="发表于 2022-11-09 20:55:33">2022-11-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/11/09/123/" title="123"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="123"/></a><div class="content"><a class="title" href="/2022/11/09/123/" title="123">123</a><time datetime="2022-11-09T12:40:11.000Z" title="发表于 2022-11-09 20:40:11">2022-11-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/11/09/ES6%E6%96%B0%E7%89%B9%E6%80%A7-1/" title="ES6新特性"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="ES6新特性"/></a><div class="content"><a class="title" href="/2022/11/09/ES6%E6%96%B0%E7%89%B9%E6%80%A7-1/" title="ES6新特性">ES6新特性</a><time datetime="2022-11-09T12:38:06.000Z" title="发表于 2022-11-09 20:38:06">2022-11-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/11/09/ES6%E6%96%B0%E7%89%B9%E6%80%A7/" title="ES6新特性"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="ES6新特性"/></a><div class="content"><a class="title" href="/2022/11/09/ES6%E6%96%B0%E7%89%B9%E6%80%A7/" title="ES6新特性">ES6新特性</a><time datetime="2022-11-09T12:35:33.000Z" title="发表于 2022-11-09 20:35:33">2022-11-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue 响应式解析"/></a><div class="content"><a class="title" href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析">Vue 响应式解析</a><time datetime="2022-10-20T12:05:37.000Z" title="发表于 2022-10-20 20:05:37">2022-10-20</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2022 By Justic</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a><img src= "" data-lazy-src="https://static.dy208.cn/o_1dfilp8ruo521thr1hvf18ji17soa.png">
<a href="http://www.beian.miit.gov.cn/"  style="color:#f72b07" target="_blank">晋ICP备2021014440号-2</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="chat_btn" type="button" title="聊天"><i class="fas fa-sms"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div></div></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="/js/search/local-search.js"></script><div class="js-pjax"><script>function loadValine () {
  function initValine () {
    const valine = new Valine(Object.assign({
      el: '#vcomment',
      appId: 'KgIigedIwh0GobYsWWfPMEdO-gzGzoHsz',
      appKey: 'WpJEQP22asTau19i2tq1yQhU',
      avatar: 'justic',
      serverURLs: '',
      emojiMaps: "",
      path: window.location.pathname,
      visitor: false
    }, null))
  }

  if (typeof Valine === 'function') initValine() 
  else getScript('https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js').then(initValine)
}

if ('Valine' === 'Valine' || !false) {
  if (false) btf.loadComment(document.getElementById('vcomment'),loadValine)
  else setTimeout(loadValine, 0)
} else {
  function loadOtherComment () {
    loadValine()
  }
}</script></div><div class="aplayer no-destroy" data-id="5076309057" data-server="netease" data-type="playlist" data-fixed="true" data-autoplay="true" data-lrcType="-1"> </div><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = false;
POWERMODE.mobile = true;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-show-text" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/click-show-text.min.js" data-mobile="true" data-text="富强,民主,文明,和谐,平等,公正,法治,爱国,敬业,诚信,友善" data-fontsize="15px" data-random="true" async="async"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/metingjs/dist/Meting.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><!-- hexo injector body_end start --><script data-pjax>
  function butterfly_clock_anzhiyu_injector_config(){
    var parent_div_git = document.getElementsByClassName('sticky_layout')[0];
    var item_html = '<div class="card-widget card-clock"><div class="card-glass"><div class="card-background"><div class="card-content"><div id="hexo_electric_clock"><img class="entered loading" id="card-clock-loading" src= "" data-lazy-src="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/loading.gif" style="height: 120px; width: 100%;" data-ll-status="loading"/></div></div></div></div></div>';
    console.log('已挂载butterfly_clock_anzhiyu')
    parent_div_git.insertAdjacentHTML("afterbegin",item_html)
    }
  var elist = 'null'.split(',');
  var cpage = location.pathname;
  var epage = 'all';
  var qweather_key = 'f854dfdd82d747fca7fd04f092861e87';
  var gaud_map_key = '427416c518f4476a01117be40057a892';
  var baidu_ak_key = 'undefined';
  var flag = 0;
  var clock_rectangle = '112.982279,28.19409';
  var clock_default_rectangle_enable = 'false';

  for (var i=0;i<elist.length;i++){
    if (cpage.includes(elist[i])){
      flag++;
    }
  }

  if ((epage ==='all')&&(flag == 0)){
    butterfly_clock_anzhiyu_injector_config();
  }
  else if (epage === cpage){
    butterfly_clock_anzhiyu_injector_config();
  }
  </script><script src="https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0"></script><script data-pjax src="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.js"></script><!-- hexo injector body_end end --></body></html>